API-Review Strongly-typed collections for a few options types.

We don't want these extensions methods defined in a wierd namespace, it's
straightforward and future-proof to just make these strongly-typed
collections.
This commit is contained in:
Ryan Nowak 2015-09-20 22:10:08 -07:00
parent 895258d550
commit 9badd9386e
6 changed files with 80 additions and 106 deletions

View File

@ -1,43 +0,0 @@
// 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;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Extensions for <see cref="IList{IExcludeTypeValidationFilter}"/>.
/// </summary>
public static class ExcludeTypeValidationFilterExtensions
{
/// <summary>
/// Adds a descriptor to the specified <paramref name="excludeTypeValidationFilters" /> that excludes the properties of
/// the <see cref="Type"/> specified and its derived types from validaton.
/// </summary>
/// <param name="excludeTypeValidationFilters">A list of <see cref="IExcludeTypeValidationFilter"/> which are used to
/// get a collection of exclude filters to be applied for filtering model properties during validation.
/// </param>
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
public static void Add(this IList<IExcludeTypeValidationFilter> excludeTypeValidationFilters, Type type)
{
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
excludeTypeValidationFilters.Add(typeBasedExcludeFilter);
}
/// <summary>
/// Adds a descriptor to the specified <paramref name="excludeTypeValidationFilters" /> that excludes the properties of
/// the type specified and its derived types from validaton.
/// </summary>
/// <param name="excludeTypeValidationFilters">A list of <see cref="IExcludeTypeValidationFilter"/> which are used to
/// get a collection of exclude filters to be applied for filtering model properties during validation.
/// </param>
/// <param name="typeFullName">Full name of the type which should be excluded from validation.</param>
public static void Add(this IList<IExcludeTypeValidationFilter> excludeTypeValidationFilters, string typeFullName)
{
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
excludeTypeValidationFilters.Add(filter);
}
}
}

View File

@ -1,110 +1,96 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic; using System.Collections.ObjectModel;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc.Filters
{ {
/// <summary> public class FilterCollection : Collection<IFilterMetadata>
/// Extension methods for adding filters to the global filters collection.
/// </summary>
public static class FilterCollectionExtensions
{ {
/// <summary> /// <summary>
/// Adds a type representing an <see cref="IFilterMetadata"/> to a filter collection. /// Adds a type representing an <see cref="IFilterMetadata"/>.
/// </summary> /// </summary>
/// <param name="filters">A collection of <see cref="IFilterMetadata"/>.</param>
/// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param> /// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param>
/// <returns>An <see cref="IFilterMetadata"/> representing the added type.</returns> /// <returns>An <see cref="IFilterMetadata"/> representing the added type.</returns>
/// <remarks> /// <remarks>
/// Filter instances will be created using /// Filter instances will be created using
/// <see cref="Microsoft.Framework.DependencyInjection.ActivatorUtilities"/>. /// <see cref="Microsoft.Framework.DependencyInjection.ActivatorUtilities"/>.
/// Use <see cref="AddService(ICollection{IFilterMetadata}, Type)"/> to register a service as a filter. /// Use <see cref="AddService(Type)"/> to register a service as a filter.
/// </remarks> /// </remarks>
public static IFilterMetadata Add( public IFilterMetadata Add([NotNull] Type filterType)
[NotNull] this ICollection<IFilterMetadata> filters,
[NotNull] Type filterType)
{ {
return Add(filters, filterType, order: 0); return Add(filterType, order: 0);
} }
/// <summary> /// <summary>
/// Adds a type representing an <see cref="IFilterMetadata"/> to a filter collection. /// Adds a type representing an <see cref="IFilterMetadata"/>.
/// </summary> /// </summary>
/// <param name="filters">A collection of <see cref="IFilterMetadata"/>.</param>
/// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param> /// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param>
/// <param name="order">The order of the added filter.</param> /// <param name="order">The order of the added filter.</param>
/// <returns>An <see cref="IFilterMetadata"/> representing the added type.</returns> /// <returns>An <see cref="IFilterMetadata"/> representing the added type.</returns>
/// <remarks> /// <remarks>
/// Filter instances will be created using /// Filter instances will be created using
/// <see cref="Microsoft.Framework.DependencyInjection.ActivatorUtilities"/>. /// <see cref="Microsoft.Framework.DependencyInjection.ActivatorUtilities"/>.
/// Use <see cref="AddService(ICollection{IFilterMetadata}, Type)"/> to register a service as a filter. /// Use <see cref="AddService(Type)"/> to register a service as a filter.
/// </remarks> /// </remarks>
public static IFilterMetadata Add( public IFilterMetadata Add([NotNull] Type filterType, int order)
[NotNull] this ICollection<IFilterMetadata> filters,
[NotNull] Type filterType,
int order)
{ {
if (!typeof(IFilterMetadata).IsAssignableFrom(filterType)) if (!typeof(IFilterMetadata).IsAssignableFrom(filterType))
{ {
var message = Resources.FormatTypeMustDeriveFromType(filterType.FullName, typeof(IFilterMetadata).FullName); var message = Resources.FormatTypeMustDeriveFromType(
filterType.FullName,
typeof(IFilterMetadata).FullName);
throw new ArgumentException(message, nameof(filterType)); throw new ArgumentException(message, nameof(filterType));
} }
var filter = new TypeFilterAttribute(filterType) { Order = order }; var filter = new TypeFilterAttribute(filterType) { Order = order };
filters.Add(filter); Add(filter);
return filter; return filter;
} }
/// <summary> /// <summary>
/// Adds a type representing an <see cref="IFilterMetadata"/> to a filter collection. /// Adds a type representing an <see cref="IFilterMetadata"/>.
/// </summary> /// </summary>
/// <param name="filters">A collection of <see cref="IFilterMetadata"/>.</param>
/// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param> /// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param>
/// <returns>An <see cref="IFilterMetadata"/> representing the added service type.</returns> /// <returns>An <see cref="IFilterMetadata"/> representing the added service type.</returns>
/// <remarks> /// <remarks>
/// Filter instances will created through dependency injection. Use /// Filter instances will created through dependency injection. Use
/// <see cref="AddService(ICollection{IFilterMetadata}, Type)"/> to register a service that will be created via /// <see cref="Add(Type)"/> to register a service that will be created via
/// type activation. /// type activation.
/// </remarks> /// </remarks>
public static IFilterMetadata AddService( public IFilterMetadata AddService([NotNull] Type filterType)
[NotNull] this ICollection<IFilterMetadata> filters,
[NotNull] Type filterType)
{ {
return AddService(filters, filterType, order: 0); return AddService(filterType, order: 0);
} }
/// <summary> /// <summary>
/// Adds a type representing an <see cref="IFilterMetadata"/> to a filter collection. /// Adds a type representing an <see cref="IFilterMetadata"/>.
/// </summary> /// </summary>
/// <param name="filters">A collection of <see cref="IFilterMetadata"/>.</param>
/// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param> /// <param name="filterType">Type representing an <see cref="IFilterMetadata"/>.</param>
/// <param name="order">The order of the added filter.</param> /// <param name="order">The order of the added filter.</param>
/// <returns>An <see cref="IFilterMetadata"/> representing the added service type.</returns> /// <returns>An <see cref="IFilterMetadata"/> representing the added service type.</returns>
/// <remarks> /// <remarks>
/// Filter instances will created through dependency injection. Use /// Filter instances will created through dependency injection. Use
/// <see cref="AddService(ICollection{IFilterMetadata}, Type)"/> to register a service that will be created via /// <see cref="Add(Type)"/> to register a service that will be created via
/// type activation. /// type activation.
/// </remarks> /// </remarks>
public static IFilterMetadata AddService( public IFilterMetadata AddService([NotNull] Type filterType, int order)
[NotNull] this ICollection<IFilterMetadata> filters,
[NotNull] Type filterType,
int order)
{ {
if (!typeof(IFilterMetadata).GetTypeInfo().IsAssignableFrom(filterType.GetTypeInfo())) if (!typeof(IFilterMetadata).GetTypeInfo().IsAssignableFrom(filterType.GetTypeInfo()))
{ {
var message = Resources.FormatTypeMustDeriveFromType(filterType.FullName, typeof(IFilterMetadata).FullName); var message = Resources.FormatTypeMustDeriveFromType(
filterType.FullName,
typeof(IFilterMetadata).FullName);
throw new ArgumentException(message, nameof(filterType)); throw new ArgumentException(message, nameof(filterType));
} }
var filter = new ServiceFilterAttribute(filterType) { Order = order }; var filter = new ServiceFilterAttribute(filterType) { Order = order };
filters.Add(filter); Add(filter);
return filter; return filter;
} }
} }
} }

View File

@ -0,0 +1,34 @@
// 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;
using System.Collections.ObjectModel;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
{
public class ExcludeTypeValidationFilterCollection : Collection<IExcludeTypeValidationFilter>
{
/// <summary>
/// Adds an <see cref="IExcludeTypeValidationFilter"/> that excludes the properties of
/// the <see cref="Type"/> specified and its derived types from validaton.
/// </summary>
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
public void Add([NotNull] Type type)
{
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
Add(typeBasedExcludeFilter);
}
/// <summary>
/// Adds an <see cref="IExcludeTypeValidationFilter"/> that excludes the properties of
/// the <see cref="Type"/> specified and its derived types from validaton.
/// </summary>
/// <param name="typeFullName">Full name of the type which should be excluded from validation.</param>
public void Add([NotNull] string typeFullName)
{
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
Add(filter);
}
}
}

View File

@ -23,14 +23,14 @@ namespace Microsoft.AspNet.Mvc
{ {
CacheProfiles = new Dictionary<string, CacheProfile>(StringComparer.OrdinalIgnoreCase); CacheProfiles = new Dictionary<string, CacheProfile>(StringComparer.OrdinalIgnoreCase);
Conventions = new List<IApplicationModelConvention>(); Conventions = new List<IApplicationModelConvention>();
Filters = new List<IFilterMetadata>(); Filters = new FilterCollection();
FormatterMappings = new FormatterMappings(); FormatterMappings = new FormatterMappings();
InputFormatters = new List<IInputFormatter>(); InputFormatters = new List<IInputFormatter>();
OutputFormatters = new List<IOutputFormatter>(); OutputFormatters = new List<IOutputFormatter>();
ModelBinders = new List<IModelBinder>(); ModelBinders = new List<IModelBinder>();
ModelMetadataDetailsProviders = new List<IMetadataDetailsProvider>(); ModelMetadataDetailsProviders = new List<IMetadataDetailsProvider>();
ModelValidatorProviders = new List<IModelValidatorProvider>(); ModelValidatorProviders = new List<IModelValidatorProvider>();
ValidationExcludeFilters = new List<IExcludeTypeValidationFilter>(); ValidationExcludeFilters = new ExcludeTypeValidationFilterCollection();
ValueProviderFactories = new List<IValueProviderFactory>(); ValueProviderFactories = new List<IValueProviderFactory>();
} }
@ -47,10 +47,10 @@ namespace Microsoft.AspNet.Mvc
public IList<IApplicationModelConvention> Conventions { get; } public IList<IApplicationModelConvention> Conventions { get; }
/// <summary> /// <summary>
/// Gets a list of <see cref="IFilterMetadata"/> which are used to construct filters that /// Gets a collection of <see cref="IFilterMetadata"/> which are used to construct filters that
/// apply to all actions. /// apply to all actions.
/// </summary> /// </summary>
public ICollection<IFilterMetadata> Filters { get; } public FilterCollection Filters { get; }
/// <summary> /// <summary>
/// Used to specify mapping between the URL Format and corresponding /// Used to specify mapping between the URL Format and corresponding
@ -118,9 +118,9 @@ namespace Microsoft.AspNet.Mvc
public bool RespectBrowserAcceptHeader { get; set; } public bool RespectBrowserAcceptHeader { get; set; }
/// <summary> /// <summary>
/// Gets a list of <see cref="IExcludeTypeValidationFilter"/>s that are used by this application. /// Gets a collection of <see cref="IExcludeTypeValidationFilter"/>s that are used by this application.
/// </summary> /// </summary>
public IList<IExcludeTypeValidationFilter> ValidationExcludeFilters { get; } public ExcludeTypeValidationFilterCollection ValidationExcludeFilters { get; }
/// <summary> /// <summary>
/// Gets a list of <see cref="IValueProviderFactory"/> used by this application. /// Gets a list of <see cref="IValueProviderFactory"/> used by this application.

View File

@ -2,19 +2,17 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.ObjectModel;
using Microsoft.AspNet.Mvc.Filters;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc.Filters
{ {
public class FilterCollectionExtensionsTest public class FilterCollectionTest
{ {
[Fact] [Fact]
public void Add_UsesTypeFilterAttribute() public void Add_UsesTypeFilterAttribute()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
// Act // Act
var added = collection.Add(typeof(MyFilter)); var added = collection.Add(typeof(MyFilter));
@ -29,7 +27,7 @@ namespace Microsoft.AspNet.Mvc
public void Add_WithOrder_SetsOrder() public void Add_WithOrder_SetsOrder()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
// Act // Act
var added = collection.Add(typeof(MyFilter), 17); var added = collection.Add(typeof(MyFilter), 17);
@ -42,10 +40,10 @@ namespace Microsoft.AspNet.Mvc
public void Add_ThrowsOnNonIFilter() public void Add_ThrowsOnNonIFilter()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
var expectedMessage = var expectedMessage =
"The type 'Microsoft.AspNet.Mvc.FilterCollectionExtensionsTest+NonFilter' must derive from " + $"The type '{typeof(NonFilter).FullName}' must derive from " +
$"'{typeof(IFilterMetadata).FullName}'." + Environment.NewLine + $"'{typeof(IFilterMetadata).FullName}'." + Environment.NewLine +
"Parameter name: filterType"; "Parameter name: filterType";
@ -60,7 +58,7 @@ namespace Microsoft.AspNet.Mvc
public void AddService_UsesServiceFilterAttribute() public void AddService_UsesServiceFilterAttribute()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
// Act // Act
var added = collection.AddService(typeof(MyFilter)); var added = collection.AddService(typeof(MyFilter));
@ -75,7 +73,7 @@ namespace Microsoft.AspNet.Mvc
public void AddService_SetsOrder() public void AddService_SetsOrder()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
// Act // Act
var added = collection.AddService(typeof(MyFilter), 17); var added = collection.AddService(typeof(MyFilter), 17);
@ -88,10 +86,10 @@ namespace Microsoft.AspNet.Mvc
public void AddService_ThrowsOnNonIFilter() public void AddService_ThrowsOnNonIFilter()
{ {
// Arrange // Arrange
var collection = new Collection<IFilterMetadata>(); var collection = new FilterCollection();
var expectedMessage = var expectedMessage =
"The type 'Microsoft.AspNet.Mvc.FilterCollectionExtensionsTest+NonFilter' must derive from " + $"The type '{typeof(NonFilter).FullName}' must derive from " +
$"'{typeof(IFilterMetadata).FullName}'." + Environment.NewLine + $"'{typeof(IFilterMetadata).FullName}'." + Environment.NewLine +
"Parameter name: filterType"; "Parameter name: filterType";

View File

@ -1,20 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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.ModelBinding.Validation; using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class ExcludeTypeValidationFilterExtensionsTests public class ExcludeTypeValidationFilterCollectionTest
{ {
[Fact] [Fact]
public void AddFilter_ByType() public void AddFilter_ByType()
{ {
// Arrange // Arrange
var type = typeof(BaseType); var type = typeof(BaseType);
var collection = new List<IExcludeTypeValidationFilter>(); var collection = new ExcludeTypeValidationFilterCollection();
// Act // Act
collection.Add(type); collection.Add(type);
@ -29,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
// Arrange // Arrange
var type = typeof(BaseType); var type = typeof(BaseType);
var collection = new List<IExcludeTypeValidationFilter>(); var collection = new ExcludeTypeValidationFilterCollection();
// Act // Act
collection.Add(type.FullName); collection.Add(type.FullName);