Adds common interfaces around Models (Implements #3158)
This commit is contained in:
parent
9c81b95d1b
commit
49acfd562e
|
|
@ -12,6 +12,30 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BindingInfo
|
public class BindingInfo
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="BindingInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
public BindingInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a copy of a <see cref="BindingInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The <see cref="BindingInfo"/> to copy.</param>
|
||||||
|
public BindingInfo(BindingInfo other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingSource = other.BindingSource;
|
||||||
|
BinderModelName = other.BinderModelName;
|
||||||
|
BinderType = other.BinderType;
|
||||||
|
PropertyBindingPredicateProvider = other.PropertyBindingPredicateProvider;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the <see cref="ModelBinding.BindingSource"/>.
|
/// Gets or sets the <see cref="ModelBinding.BindingSource"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
[DebuggerDisplay("Name={ActionName}({Methods()}), Type={Controller.ControllerType.Name}," +
|
[DebuggerDisplay("Name={ActionName}({Methods()}), Type={Controller.ControllerType.Name}," +
|
||||||
" Route: {AttributeRouteModel?.Template}, Filters: {Filters.Count}")]
|
" Route: {AttributeRouteModel?.Template}, Filters: {Filters.Count}")]
|
||||||
public class ActionModel
|
public class ActionModel : ICommonModel, IFilterModel, IApiExplorerModel
|
||||||
{
|
{
|
||||||
public ActionModel(
|
public ActionModel(
|
||||||
[NotNull] MethodInfo actionMethod,
|
[NotNull] MethodInfo actionMethod,
|
||||||
|
|
@ -100,6 +100,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public IDictionary<object, object> Properties { get; }
|
public IDictionary<object, object> Properties { get; }
|
||||||
|
|
||||||
|
MemberInfo ICommonModel.MemberInfo => ActionMethod;
|
||||||
|
|
||||||
|
string ICommonModel.Name => ActionName;
|
||||||
|
|
||||||
private string Methods()
|
private string Methods()
|
||||||
{
|
{
|
||||||
if (HttpMethods.Count == 0)
|
if (HttpMethods.Count == 0)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNet.Mvc.Filters;
|
||||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
[DebuggerDisplay("ApplicationModel: Controllers: {Controllers.Count}, Filters: {Filters.Count}")]
|
[DebuggerDisplay("ApplicationModel: Controllers: {Controllers.Count}, Filters: {Filters.Count}")]
|
||||||
public class ApplicationModel
|
public class ApplicationModel : IPropertyModel, IFilterModel, IApiExplorerModel
|
||||||
{
|
{
|
||||||
public ApplicationModel()
|
public ApplicationModel()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
[DebuggerDisplay("Name={ControllerName}, Type={ControllerType.Name}," +
|
[DebuggerDisplay("Name={ControllerName}, Type={ControllerType.Name}," +
|
||||||
" Routes: {AttributeRoutes.Count}, Filters: {Filters.Count}")]
|
" Routes: {AttributeRoutes.Count}, Filters: {Filters.Count}")]
|
||||||
public class ControllerModel
|
public class ControllerModel : ICommonModel, IFilterModel, IApiExplorerModel
|
||||||
{
|
{
|
||||||
public ControllerModel(
|
public ControllerModel(
|
||||||
[NotNull] TypeInfo controllerType,
|
[NotNull] TypeInfo controllerType,
|
||||||
|
|
@ -79,6 +79,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
|
||||||
public IReadOnlyList<object> Attributes { get; }
|
public IReadOnlyList<object> Attributes { get; }
|
||||||
|
|
||||||
|
MemberInfo ICommonModel.MemberInfo => ControllerType;
|
||||||
|
|
||||||
|
string ICommonModel.Name => ControllerName;
|
||||||
|
|
||||||
public string ControllerName { get; set; }
|
public string ControllerName { get; set; }
|
||||||
|
|
||||||
public TypeInfo ControllerType { get; private set; }
|
public TypeInfo ControllerType { get; private set; }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
{
|
||||||
|
public interface IApiExplorerModel
|
||||||
|
{
|
||||||
|
ApiExplorerModel ApiExplorer { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
{
|
||||||
|
public interface IBindingModel
|
||||||
|
{
|
||||||
|
BindingInfo BindingInfo { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
{
|
||||||
|
public interface ICommonModel : IPropertyModel
|
||||||
|
{
|
||||||
|
IReadOnlyList<object> Attributes { get; }
|
||||||
|
MemberInfo MemberInfo { get; }
|
||||||
|
string Name { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.Filters;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
{
|
||||||
|
public interface IFilterModel
|
||||||
|
{
|
||||||
|
IList<IFilterMetadata> Filters { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
|
{
|
||||||
|
public interface IPropertyModel
|
||||||
|
{
|
||||||
|
IDictionary<object, object> Properties { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,14 +10,14 @@ using Microsoft.Framework.Internal;
|
||||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
[DebuggerDisplay("ParameterModel: Name={ParameterName}")]
|
[DebuggerDisplay("ParameterModel: Name={ParameterName}")]
|
||||||
public class ParameterModel
|
public class ParameterModel : ICommonModel, IBindingModel
|
||||||
{
|
{
|
||||||
public ParameterModel(
|
public ParameterModel(
|
||||||
[NotNull] ParameterInfo parameterInfo,
|
[NotNull] ParameterInfo parameterInfo,
|
||||||
[NotNull] IReadOnlyList<object> attributes)
|
[NotNull] IReadOnlyList<object> attributes)
|
||||||
{
|
{
|
||||||
ParameterInfo = parameterInfo;
|
ParameterInfo = parameterInfo;
|
||||||
|
Properties = new Dictionary<object, object>();
|
||||||
Attributes = new List<object>(attributes);
|
Attributes = new List<object>(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,15 +25,22 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
Action = other.Action;
|
Action = other.Action;
|
||||||
Attributes = new List<object>(other.Attributes);
|
Attributes = new List<object>(other.Attributes);
|
||||||
BindingInfo = other.BindingInfo;
|
BindingInfo = other.BindingInfo == null ? null : new BindingInfo(other.BindingInfo);
|
||||||
ParameterInfo = other.ParameterInfo;
|
ParameterInfo = other.ParameterInfo;
|
||||||
ParameterName = other.ParameterName;
|
ParameterName = other.ParameterName;
|
||||||
|
Properties = new Dictionary<object, object>(other.Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionModel Action { get; set; }
|
public ActionModel Action { get; set; }
|
||||||
|
|
||||||
public IReadOnlyList<object> Attributes { get; }
|
public IReadOnlyList<object> Attributes { get; }
|
||||||
|
|
||||||
|
public IDictionary<object, object> Properties { get; }
|
||||||
|
|
||||||
|
MemberInfo ICommonModel.MemberInfo => ParameterInfo.Member;
|
||||||
|
|
||||||
|
string ICommonModel.Name => ParameterName;
|
||||||
|
|
||||||
public ParameterInfo ParameterInfo { get; private set; }
|
public ParameterInfo ParameterInfo { get; private set; }
|
||||||
|
|
||||||
public string ParameterName { get; set; }
|
public string ParameterName { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
/// A type which is used to represent a property in a <see cref="ControllerModel"/>.
|
/// A type which is used to represent a property in a <see cref="ControllerModel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DebuggerDisplay("PropertyModel: Name={PropertyName}")]
|
[DebuggerDisplay("PropertyModel: Name={PropertyName}")]
|
||||||
public class PropertyModel
|
public class PropertyModel : ICommonModel, IBindingModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of <see cref="PropertyModel"/>.
|
/// Creates a new instance of <see cref="PropertyModel"/>.
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
[NotNull] IReadOnlyList<object> attributes)
|
[NotNull] IReadOnlyList<object> attributes)
|
||||||
{
|
{
|
||||||
PropertyInfo = propertyInfo;
|
PropertyInfo = propertyInfo;
|
||||||
|
Properties = new Dictionary<object, object>();
|
||||||
Attributes = new List<object>(attributes);
|
Attributes = new List<object>(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,9 +37,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
Controller = other.Controller;
|
Controller = other.Controller;
|
||||||
Attributes = new List<object>(other.Attributes);
|
Attributes = new List<object>(other.Attributes);
|
||||||
BindingInfo = other.BindingInfo;
|
BindingInfo = BindingInfo == null ? null : new BindingInfo(other.BindingInfo);
|
||||||
PropertyInfo = other.PropertyInfo;
|
PropertyInfo = other.PropertyInfo;
|
||||||
PropertyName = other.PropertyName;
|
PropertyName = other.PropertyName;
|
||||||
|
Properties = new Dictionary<object, object>(other.Properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -52,6 +53,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<object> Attributes { get; }
|
public IReadOnlyList<object> Attributes { get; }
|
||||||
|
|
||||||
|
public IDictionary<object, object> Properties { get; }
|
||||||
|
|
||||||
|
MemberInfo ICommonModel.MemberInfo => PropertyInfo;
|
||||||
|
|
||||||
|
string ICommonModel.Name => PropertyName;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the <see cref="BindingInfo"/> associated with this model.
|
/// Gets or sets the <see cref="BindingInfo"/> associated with this model.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
};
|
};
|
||||||
|
|
||||||
parameter.ParameterName = "id";
|
parameter.ParameterName = "id";
|
||||||
|
parameter.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var parameter2 = new ParameterModel(parameter);
|
var parameter2 = new ParameterModel(parameter);
|
||||||
|
|
@ -32,6 +33,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
// Assert
|
// Assert
|
||||||
foreach (var property in typeof(ParameterModel).GetProperties())
|
foreach (var property in typeof(ParameterModel).GetProperties())
|
||||||
{
|
{
|
||||||
|
if (property.Name.Equals("BindingInfo"))
|
||||||
|
{
|
||||||
|
// This test excludes other mutable objects on purpose because we deep copy them.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var value1 = property.GetValue(parameter);
|
var value1 = property.GetValue(parameter);
|
||||||
var value2 = property.GetValue(parameter2);
|
var value2 = property.GetValue(parameter2);
|
||||||
|
|
||||||
|
|
@ -42,6 +49,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
// Ensure non-default value
|
// Ensure non-default value
|
||||||
Assert.NotEmpty((IEnumerable<object>)value1);
|
Assert.NotEmpty((IEnumerable<object>)value1);
|
||||||
}
|
}
|
||||||
|
else if (typeof(IDictionary<object, object>).IsAssignableFrom(property.PropertyType))
|
||||||
|
{
|
||||||
|
Assert.Equal(value1, value2);
|
||||||
|
|
||||||
|
// Ensure non-default value
|
||||||
|
Assert.NotEmpty((IDictionary<object, object>)value1);
|
||||||
|
}
|
||||||
else if (property.PropertyType.IsValueType ||
|
else if (property.PropertyType.IsValueType ||
|
||||||
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
propertyModel.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(), new List<object>());
|
propertyModel.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(), new List<object>());
|
||||||
propertyModel.BindingInfo = BindingInfo.GetBindingInfo(propertyModel.Attributes);
|
propertyModel.BindingInfo = BindingInfo.GetBindingInfo(propertyModel.Attributes);
|
||||||
propertyModel.PropertyName = "Property";
|
propertyModel.PropertyName = "Property";
|
||||||
|
propertyModel.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var propertyModel2 = new PropertyModel(propertyModel);
|
var propertyModel2 = new PropertyModel(propertyModel);
|
||||||
|
|
@ -28,6 +29,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
// Assert
|
// Assert
|
||||||
foreach (var property in typeof(PropertyModel).GetProperties())
|
foreach (var property in typeof(PropertyModel).GetProperties())
|
||||||
{
|
{
|
||||||
|
if (property.Name.Equals("BindingInfo"))
|
||||||
|
{
|
||||||
|
// This test excludes other mutable objects on purpose because we deep copy them.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var value1 = property.GetValue(propertyModel);
|
var value1 = property.GetValue(propertyModel);
|
||||||
var value2 = property.GetValue(propertyModel2);
|
var value2 = property.GetValue(propertyModel2);
|
||||||
|
|
||||||
|
|
@ -38,6 +45,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
// Ensure non-default value
|
// Ensure non-default value
|
||||||
Assert.NotEmpty((IEnumerable<object>)value1);
|
Assert.NotEmpty((IEnumerable<object>)value1);
|
||||||
}
|
}
|
||||||
|
else if (typeof(IDictionary<object, object>).IsAssignableFrom(property.PropertyType))
|
||||||
|
{
|
||||||
|
Assert.Equal(value1, value2);
|
||||||
|
|
||||||
|
// Ensure non-default value
|
||||||
|
Assert.NotEmpty((IDictionary<object, object>)value1);
|
||||||
|
}
|
||||||
else if (property.PropertyType.IsValueType ||
|
else if (property.PropertyType.IsValueType ||
|
||||||
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue