diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs
index 7d53e0273e..401febb5cf 100644
--- a/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs
@@ -1,6 +1,7 @@
// 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 System.Collections.ObjectModel;
@@ -34,11 +35,20 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
///
/// The type to remove.
public void RemoveType() where T : TFormatter
+ {
+ RemoveType(typeof(T));
+ }
+
+ ///
+ /// Removes all formatters of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type formatterType)
{
for (var i = Count - 1; i >= 0; i--)
{
var formatter = this[i];
- if (formatter is T)
+ if (formatter.GetType() == formatterType)
{
RemoveAt(i);
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApplicationModelConventionCollection.cs b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApplicationModelConventionCollection.cs
new file mode 100644
index 0000000000..e0ee53c2ce
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ApplicationModelConventionCollection.cs
@@ -0,0 +1,57 @@
+// 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 System.Collections.ObjectModel;
+
+namespace Microsoft.AspNetCore.Mvc.ApplicationModels
+{
+ ///
+ /// Represents a collection of application model conventions.
+ ///
+ public class ApplicationModelConventionCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of the class that is empty.
+ ///
+ public ApplicationModelConventionCollection()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// as a wrapper for the specified list.
+ ///
+ /// The list that is wrapped by the new collection.
+ public ApplicationModelConventionCollection(IList applicationModelConventions)
+ : base(applicationModelConventions)
+ {
+ }
+
+ ///
+ /// Removes all application model conventions of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType() where TApplicationModelConvention : IApplicationModelConvention
+ {
+ RemoveType(typeof(TApplicationModelConvention));
+ }
+
+ ///
+ /// Removes all application model conventions of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type applicationModelConventionType)
+ {
+ for (var i = Count - 1; i >= 0; i--)
+ {
+ var applicationModelConvention = this[i];
+ if (applicationModelConvention.GetType() == applicationModelConventionType)
+ {
+ RemoveAt(i);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/MetadataDetailsProviderCollection.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/MetadataDetailsProviderCollection.cs
new file mode 100644
index 0000000000..4eba80f496
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/MetadataDetailsProviderCollection.cs
@@ -0,0 +1,57 @@
+// 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 System.Collections.ObjectModel;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
+{
+ ///
+ /// Represents a collection of metadata details providers.
+ ///
+ public class MetadataDetailsProviderCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of the class that is empty.
+ ///
+ public MetadataDetailsProviderCollection()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// as a wrapper for the specified list.
+ ///
+ /// The list that is wrapped by the new collection.
+ public MetadataDetailsProviderCollection(IList metadataDetailsProviders)
+ : base(metadataDetailsProviders)
+ {
+ }
+
+ ///
+ /// Removes all metadata details providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType() where TMetadataDetailsProvider : IMetadataDetailsProvider
+ {
+ RemoveType(typeof(TMetadataDetailsProvider));
+ }
+
+ ///
+ /// Removes all metadata details providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type metadataDetailsProviderType)
+ {
+ for (var i = Count - 1; i >= 0; i--)
+ {
+ var metadataDetailsProvider = this[i];
+ if (metadataDetailsProvider.GetType() == metadataDetailsProviderType)
+ {
+ RemoveAt(i);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderProviderCollection.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderProviderCollection.cs
new file mode 100644
index 0000000000..0bfccb3e10
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBinderProviderCollection.cs
@@ -0,0 +1,57 @@
+// 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 System.Collections.ObjectModel;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding
+{
+ ///
+ /// Represents a collection of model binder providers.
+ ///
+ public class ModelBinderProviderCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of the class that is empty.
+ ///
+ public ModelBinderProviderCollection()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// as a wrapper for the specified list.
+ ///
+ /// The list that is wrapped by the new collection.
+ public ModelBinderProviderCollection(IList modelBinderProviders)
+ : base(modelBinderProviders)
+ {
+ }
+
+ ///
+ /// Removes all model binder providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType() where TModelBinderProvider : IModelBinderProvider
+ {
+ RemoveType(typeof(TModelBinderProvider));
+ }
+
+ ///
+ /// Removes all model binder providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type modelBinderProviderType)
+ {
+ for (var i = Count - 1; i >= 0; i--)
+ {
+ var modelBinderProvider = this[i];
+ if (modelBinderProvider.GetType() == modelBinderProviderType)
+ {
+ RemoveAt(i);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/ModelValidatorProviderCollection.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/ModelValidatorProviderCollection.cs
new file mode 100644
index 0000000000..58e9213ca2
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/ModelValidatorProviderCollection.cs
@@ -0,0 +1,57 @@
+// 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 System.Collections.ObjectModel;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
+{
+ ///
+ /// Represents a collection of model validator providers.
+ ///
+ public class ModelValidatorProviderCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of the class that is empty.
+ ///
+ public ModelValidatorProviderCollection()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// as a wrapper for the specified list.
+ ///
+ /// The list that is wrapped by the new collection.
+ public ModelValidatorProviderCollection(IList modelValidatorProviders)
+ : base(modelValidatorProviders)
+ {
+ }
+
+ ///
+ /// Removes all model validator providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType() where TModelValidatorProvider : IModelValidatorProvider
+ {
+ RemoveType(typeof(TModelValidatorProvider));
+ }
+
+ ///
+ /// Removes all model validator providers of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type modelValidatorProviderType)
+ {
+ for (var i = Count - 1; i >= 0; i--)
+ {
+ var modelValidatorProvider = this[i];
+ if (modelValidatorProvider.GetType() == modelValidatorProviderType)
+ {
+ RemoveAt(i);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ValueProviderFactoryCollection.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ValueProviderFactoryCollection.cs
new file mode 100644
index 0000000000..e85fbd0f09
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ValueProviderFactoryCollection.cs
@@ -0,0 +1,57 @@
+// 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 System.Collections.ObjectModel;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding
+{
+ ///
+ /// Represents a collection of value provider factories.
+ ///
+ public class ValueProviderFactoryCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of the class that is empty.
+ ///
+ public ValueProviderFactoryCollection()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class
+ /// as a wrapper for the specified list.
+ ///
+ /// The list that is wrapped by the new collection.
+ public ValueProviderFactoryCollection(IList valueProviderFactories)
+ : base(valueProviderFactories)
+ {
+ }
+
+ ///
+ /// Removes all value provider factories of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType() where TValueProviderFactory : IValueProviderFactory
+ {
+ RemoveType(typeof(TValueProviderFactory));
+ }
+
+ ///
+ /// Removes all value provider factories of the specified type.
+ ///
+ /// The type to remove.
+ public void RemoveType(Type valueProviderFactoryType)
+ {
+ for (var i = Count - 1; i >= 0; i--)
+ {
+ var valueProviderFactory = this[i];
+ if (valueProviderFactory.GetType() == valueProviderFactoryType)
+ {
+ RemoveAt(i);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs b/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
index d8de256a7a..24de911424 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
@@ -22,16 +22,16 @@ namespace Microsoft.AspNetCore.Mvc
public MvcOptions()
{
CacheProfiles = new Dictionary(StringComparer.OrdinalIgnoreCase);
- Conventions = new List();
+ Conventions = new ApplicationModelConventionCollection();
Filters = new FilterCollection();
FormatterMappings = new FormatterMappings();
InputFormatters = new FormatterCollection();
OutputFormatters = new FormatterCollection();
- ModelBinderProviders = new List();
+ ModelBinderProviders = new ModelBinderProviderCollection();
ModelBindingMessageProvider = new DefaultModelBindingMessageProvider();
- ModelMetadataDetailsProviders = new List();
- ModelValidatorProviders = new List();
- ValueProviderFactories = new List();
+ ModelMetadataDetailsProviders = new MetadataDetailsProviderCollection();
+ ModelValidatorProviders = new ModelValidatorProviderCollection();
+ ValueProviderFactories = new ValueProviderFactoryCollection();
}
///
@@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Mvc
/// Gets a list of instances that will be applied to
/// the when discovering actions.
///
- public IList Conventions { get; }
+ public ApplicationModelConventionCollection Conventions { get; }
///
/// Gets a collection of which are used to construct filters that
@@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Mvc
///
/// Gets a list of s used by this application.
///
- public IList ModelBinderProviders { get; }
+ public ModelBinderProviderCollection ModelBinderProviders { get; }
///
/// Gets the default . Changes here are copied to the
@@ -122,12 +122,12 @@ namespace Microsoft.AspNetCore.Mvc
///
///
///
- public IList ModelMetadataDetailsProviders { get; }
+ public MetadataDetailsProviderCollection ModelMetadataDetailsProviders { get; }
///
/// Gets a list of s used by this application.
///
- public IList ModelValidatorProviders { get; }
+ public ModelValidatorProviderCollection ModelValidatorProviders { get; }
///
/// Gets a list of s that are used by this application.
@@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Mvc
///
/// Gets a list of used by this application.
///
- public IList ValueProviderFactories { get; }
+ public ValueProviderFactoryCollection ValueProviderFactories { get; }
///
/// Gets or sets the SSL port that is used by this application when
@@ -163,4 +163,4 @@ namespace Microsoft.AspNetCore.Mvc
///
public bool RequireHttpsPermanent { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModel/ApplicationModelConventionCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModel/ApplicationModelConventionCollectionTests.cs
new file mode 100644
index 0000000000..3202e01e30
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ApplicationModel/ApplicationModelConventionCollectionTests.cs
@@ -0,0 +1,66 @@
+// 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.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.ApplicationModels
+{
+ public class ApplicationModelConventionCollectionTests
+ {
+ [Fact]
+ public void RemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ApplicationModelConventionCollection
+ {
+ new FooApplicationModelConvention(),
+ new BarApplicationModelConvention(),
+ new FooApplicationModelConvention()
+ };
+
+ // Act
+ collection.RemoveType(typeof(FooApplicationModelConvention));
+
+ // Assert
+ var convention = Assert.Single(collection);
+ Assert.IsType(convention);
+ }
+
+ [Fact]
+ public void GenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ApplicationModelConventionCollection
+ {
+ new FooApplicationModelConvention(),
+ new BarApplicationModelConvention(),
+ new FooApplicationModelConvention()
+ };
+
+ // Act
+ collection.RemoveType();
+
+ // Assert
+ var convention = Assert.Single(collection);
+ Assert.IsType(convention);
+ }
+
+ private class FooApplicationModelConvention : IApplicationModelConvention
+ {
+ public void Apply(ApplicationModel application)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private class BarApplicationModelConvention : IApplicationModelConvention
+ {
+ public void Apply(ApplicationModel application)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/FormatterCollectionTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/FormatterCollectionTest.cs
index 741526a8ca..79922d1d62 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/FormatterCollectionTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Formatters/FormatterCollectionTest.cs
@@ -10,6 +10,25 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
{
public class FormatterCollectionTest
{
+ [Fact]
+ public void NonGenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new FormatterCollection
+ {
+ new TestOutputFormatter(),
+ new AnotherTestOutputFormatter(),
+ new TestOutputFormatter()
+ };
+
+ // Act
+ collection.RemoveType(typeof(TestOutputFormatter));
+
+ // Assert
+ var formatter = Assert.Single(collection);
+ Assert.IsType(typeof(AnotherTestOutputFormatter), formatter);
+ }
+
[Fact]
public void RemoveType_RemovesAllOfType()
{
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Metadata/MetadataDetailsProviderCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Metadata/MetadataDetailsProviderCollectionTests.cs
new file mode 100644
index 0000000000..0db4306979
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Metadata/MetadataDetailsProviderCollectionTests.cs
@@ -0,0 +1,57 @@
+// 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 Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata
+{
+ public class MetadataDetailsProviderCollectionTests
+ {
+ [Fact]
+ public void RemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new MetadataDetailsProviderCollection
+ {
+ new FooMetadataDetailsProvider(),
+ new BarMetadataDetailsProvider(),
+ new FooMetadataDetailsProvider()
+ };
+
+ // Act
+ collection.RemoveType(typeof(FooMetadataDetailsProvider));
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ [Fact]
+ public void GenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new MetadataDetailsProviderCollection
+ {
+ new FooMetadataDetailsProvider(),
+ new BarMetadataDetailsProvider(),
+ new FooMetadataDetailsProvider()
+ };
+
+ // Act
+ collection.RemoveType();
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ private class FooMetadataDetailsProvider : IMetadataDetailsProvider
+ {
+ }
+
+ private class BarMetadataDetailsProvider : IMetadataDetailsProvider
+ {
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderProviderCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderProviderCollectionTests.cs
new file mode 100644
index 0000000000..4cc5b138bf
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ModelBinderProviderCollectionTests.cs
@@ -0,0 +1,65 @@
+// 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 Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding
+{
+ public class ModelBinderProviderCollectionTests
+ {
+ [Fact]
+ public void RemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ModelBinderProviderCollection
+ {
+ new FooModelBinderProvider(),
+ new BarModelBinderProvider(),
+ new FooModelBinderProvider()
+ };
+
+ // Act
+ collection.RemoveType(typeof(FooModelBinderProvider));
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ [Fact]
+ public void GenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ModelBinderProviderCollection
+ {
+ new FooModelBinderProvider(),
+ new BarModelBinderProvider(),
+ new FooModelBinderProvider()
+ };
+
+ // Act
+ collection.RemoveType();
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ private class FooModelBinderProvider : IModelBinderProvider
+ {
+ public IModelBinder GetBinder(ModelBinderProviderContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private class BarModelBinderProvider : IModelBinderProvider
+ {
+ public IModelBinder GetBinder(ModelBinderProviderContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Validation/ModelValidatorProviderCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Validation/ModelValidatorProviderCollectionTests.cs
new file mode 100644
index 0000000000..9f4f1c1d79
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Validation/ModelValidatorProviderCollectionTests.cs
@@ -0,0 +1,65 @@
+// 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 Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
+{
+ public class ModelValidatorProviderCollectionTests
+ {
+ [Fact]
+ public void RemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ModelValidatorProviderCollection
+ {
+ new FooModelValidatorProvider(),
+ new BarModelValidatorProvider(),
+ new FooModelValidatorProvider()
+ };
+
+ // Act
+ collection.RemoveType(typeof(FooModelValidatorProvider));
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ [Fact]
+ public void GenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ModelValidatorProviderCollection
+ {
+ new FooModelValidatorProvider(),
+ new BarModelValidatorProvider(),
+ new FooModelValidatorProvider()
+ };
+
+ // Act
+ collection.RemoveType();
+
+ // Assert
+ var provider = Assert.Single(collection);
+ Assert.IsType(provider);
+ }
+
+ private class FooModelValidatorProvider : IModelValidatorProvider
+ {
+ public void CreateValidators(ModelValidatorProviderContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private class BarModelValidatorProvider : IModelValidatorProvider
+ {
+ public void CreateValidators(ModelValidatorProviderContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ValueProviderFactoryCollectionTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ValueProviderFactoryCollectionTests.cs
new file mode 100644
index 0000000000..f516d3778b
--- /dev/null
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/ValueProviderFactoryCollectionTests.cs
@@ -0,0 +1,66 @@
+// 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.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Mvc.ModelBinding
+{
+ public class ValueProviderFactoryCollectionTests
+ {
+ [Fact]
+ public void RemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ValueProviderFactoryCollection
+ {
+ new FooValueProviderFactory(),
+ new BarValueProviderFactory(),
+ new FooValueProviderFactory()
+ };
+
+ // Act
+ collection.RemoveType(typeof(FooValueProviderFactory));
+
+ // Assert
+ var factory = Assert.Single(collection);
+ Assert.IsType(factory);
+ }
+
+ [Fact]
+ public void GenericRemoveType_RemovesAllOfType()
+ {
+ // Arrange
+ var collection = new ValueProviderFactoryCollection
+ {
+ new FooValueProviderFactory(),
+ new BarValueProviderFactory(),
+ new FooValueProviderFactory()
+ };
+
+ // Act
+ collection.RemoveType();
+
+ // Assert
+ var factory = Assert.Single(collection);
+ Assert.IsType(factory);
+ }
+
+ private class FooValueProviderFactory : IValueProviderFactory
+ {
+ public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private class BarValueProviderFactory : IValueProviderFactory
+ {
+ public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}