diff --git a/src/Microsoft.AspNet.Mvc.Common/TypeExtensions.cs b/src/Microsoft.AspNet.Mvc.Common/TypeExtensions.cs index 863d1e873e..2aada1e1fd 100644 --- a/src/Microsoft.AspNet.Mvc.Common/TypeExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Common/TypeExtensions.cs @@ -45,15 +45,6 @@ namespace Microsoft.AspNet.Mvc return type.GetTypeInfo().BaseType; } - public static Type ExtractGenericInterface([NotNull] this Type queryType, Type interfaceType) - { - Func matchesInterface = - t => t.IsGenericType() && t.GetGenericTypeDefinition() == interfaceType; - return (matchesInterface(queryType)) ? - queryType : - queryType.GetInterfaces().FirstOrDefault(matchesInterface); - } - #if NETFX_CORE || DNXCORE50 public static Type[] GetGenericArguments([NotNull] this Type type) { diff --git a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActionArgumentBinder.cs b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActionArgumentBinder.cs index cc42b9905e..0244155c3b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActionArgumentBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/DefaultControllerActionArgumentBinder.cs @@ -151,8 +151,9 @@ namespace Microsoft.AspNet.Mvc } // Determine T if this is an ICollection property. - var collectionTypeArguments = propertyType - .ExtractGenericInterface(typeof(ICollection<>)) + var collectionTypeArguments = ClosedGenericMatcher.ExtractGenericInterface( + propertyType, + typeof(ICollection<>)) ?.GenericTypeArguments; if (collectionTypeArguments == null) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs index 6e8cfc93bb..c0b7ca9bfb 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs @@ -555,8 +555,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding // Determine T if this is an ICollection property. No need for a T[] case because CanUpdateProperty() // ensures property is either settable or not an array. Underlying assumption is that CanUpdateProperty() // and SetProperty() are overridden together. - var collectionTypeArguments = propertyExplorer.ModelType - .ExtractGenericInterface(typeof(ICollection<>)) + var collectionTypeArguments = ClosedGenericMatcher.ExtractGenericInterface( + propertyExplorer.ModelType, + typeof(ICollection<>)) ?.GenericTypeArguments; if (collectionTypeArguments == null) { diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Expressions/TryGetValueProvider.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Expressions/TryGetValueProvider.cs index 012819f908..c3ff41c503 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Expressions/TryGetValueProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Expressions/TryGetValueProvider.cs @@ -38,13 +38,13 @@ namespace Microsoft.AspNet.Mvc.Rendering.Expressions _tryGetValueDelegateCacheLock.ExitReadLock(); } - var dictionaryType = targetType.ExtractGenericInterface(typeof(IDictionary<,>)); + var dictionaryType = ClosedGenericMatcher.ExtractGenericInterface(targetType, typeof(IDictionary<,>)); // Just wrap a call to the underlying IDictionary.TryGetValue() where string can be cast to // TKey. if (dictionaryType != null) { - var typeArguments = dictionaryType.GetGenericArguments(); + var typeArguments = dictionaryType.GenericTypeArguments; var keyType = typeArguments[0]; var returnType = typeArguments[1]; diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs index d4b26bd9e3..b87be41910 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultDisplayTemplates.cs @@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering.Internal; using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.Rendering { @@ -106,10 +107,12 @@ namespace Microsoft.AspNet.Mvc.Rendering } var typeInCollection = typeof(string); - var genericEnumerableType = collection.GetType().ExtractGenericInterface(typeof(IEnumerable<>)); + var genericEnumerableType = ClosedGenericMatcher.ExtractGenericInterface( + collection.GetType(), + typeof(IEnumerable<>)); if (genericEnumerableType != null) { - typeInCollection = genericEnumerableType.GetGenericArguments()[0]; + typeInCollection = genericEnumerableType.GenericTypeArguments[0]; } var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType(); diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs index 0e396688c3..36cb7cf370 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/DefaultEditorTemplates.cs @@ -68,10 +68,12 @@ namespace Microsoft.AspNet.Mvc.Rendering } var typeInCollection = typeof(string); - var genericEnumerableType = collection.GetType().ExtractGenericInterface(typeof(IEnumerable<>)); + var genericEnumerableType = ClosedGenericMatcher.ExtractGenericInterface( + collection.GetType(), + typeof(IEnumerable<>)); if (genericEnumerableType != null) { - typeInCollection = genericEnumerableType.GetGenericArguments()[0]; + typeInCollection = genericEnumerableType.GenericTypeArguments[0]; } var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType(); diff --git a/src/Microsoft.AspNet.Mvc.Core/SessionStateTempDataProvider.cs b/src/Microsoft.AspNet.Mvc.Core/SessionStateTempDataProvider.cs index 238e8810c7..0a809ac835 100644 --- a/src/Microsoft.AspNet.Mvc.Core/SessionStateTempDataProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Core/SessionStateTempDataProvider.cs @@ -159,12 +159,14 @@ namespace Microsoft.AspNet.Mvc // Accessing Session property will throw if the session middleware is not enabled. var session = context.Session; - + using (var memoryStream = new MemoryStream()) - using (var writer = new BsonWriter(memoryStream)) { - _jsonSerializer.Serialize(writer, values); - session[TempDataSessionStateKey] = memoryStream.ToArray(); + using (var writer = new BsonWriter(memoryStream)) + { + _jsonSerializer.Serialize(writer, values); + session[TempDataSessionStateKey] = memoryStream.ToArray(); + } } } else if (IsSessionEnabled(context)) @@ -190,16 +192,19 @@ namespace Microsoft.AspNet.Mvc } else if (itemType.GetTypeInfo().IsGenericType) { - if (itemType.ExtractGenericInterface(typeof(IList<>)) != null) + if (ClosedGenericMatcher.ExtractGenericInterface(itemType, typeof(IList<>)) != null) { - var genericTypeArguments = itemType.GetGenericArguments(); + var genericTypeArguments = itemType.GenericTypeArguments; Debug.Assert(genericTypeArguments.Length == 1, "IList has one generic argument"); actualType = genericTypeArguments[0]; } - else if (itemType.ExtractGenericInterface(typeof(IDictionary<,>)) != null) + else if (ClosedGenericMatcher.ExtractGenericInterface(itemType, typeof(IDictionary<,>)) != null) { - var genericTypeArguments = itemType.GetGenericArguments(); - Debug.Assert(genericTypeArguments.Length == 2, "IDictionary has two generic arguments"); + var genericTypeArguments = itemType.GenericTypeArguments; + Debug.Assert( + genericTypeArguments.Length == 2, + "IDictionary has two generic arguments"); + // Throw if the key type of the dictionary is not string. if (genericTypeArguments[0] != typeof(string)) { diff --git a/src/Microsoft.AspNet.Mvc.Core/project.json b/src/Microsoft.AspNet.Mvc.Core/project.json index ad8013fec5..211cf369f0 100644 --- a/src/Microsoft.AspNet.Mvc.Core/project.json +++ b/src/Microsoft.AspNet.Mvc.Core/project.json @@ -13,18 +13,19 @@ "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.Hosting.Abstractions": "1.0.0-*", "Microsoft.AspNet.Http.Extensions": "1.0.0-*", + "Microsoft.AspNet.JsonPatch": "1.0.0-*", "Microsoft.AspNet.Mvc.Abstractions": "6.0.0-*", "Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" }, "Microsoft.AspNet.Routing": "1.0.0-*", "Microsoft.Framework.BufferEntryCollection.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.ClosedGenericMatcher.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.CopyOnWriteDictionary.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.Logging.Abstractions": "1.0.0-*", "Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.PropertyActivator.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.Runtime.Abstractions": "1.0.0-*", - "Microsoft.Framework.WebEncoders": "1.0.0-*", - "Microsoft.AspNet.JsonPatch": "1.0.0-*" + "Microsoft.Framework.WebEncoders": "1.0.0-*" }, "frameworks": { "dnx451": { diff --git a/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProvider.cs b/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProvider.cs index b58a230ec6..006e412132 100644 --- a/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProvider.cs +++ b/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProvider.cs @@ -9,7 +9,7 @@ using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.Xml { /// - /// Provides a for interface types which implement + /// Provides a for interface types which implement /// . /// public class EnumerableWrapperProvider : IWrapperProvider @@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Xml /// /// Initializes an instance of . /// - /// Type of the original + /// Type of the original /// that is being wrapped. /// The for the element type. /// Can be null. @@ -28,17 +28,19 @@ namespace Microsoft.AspNet.Mvc.Xml [NotNull] Type sourceEnumerableOfT, IWrapperProvider elementWrapperProvider) { - var enumerableOfT = sourceEnumerableOfT.ExtractGenericInterface(typeof(IEnumerable<>)); + var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface( + sourceEnumerableOfT, + typeof(IEnumerable<>)); if (!sourceEnumerableOfT.IsInterface() || enumerableOfT == null) { throw new ArgumentException( - Resources.FormatEnumerableWrapperProvider_InvalidSourceEnumerableOfT(typeof(IEnumerable<>).Name), + Resources.FormatEnumerableWrapperProvider_InvalidSourceEnumerableOfT(typeof(IEnumerable<>).Name), nameof(sourceEnumerableOfT)); } _wrapperProvider = elementWrapperProvider; - var declaredElementType = enumerableOfT.GetGenericArguments()[0]; + var declaredElementType = enumerableOfT.GenericTypeArguments[0]; var wrappedElementType = elementWrapperProvider?.WrappingType ?? declaredElementType; WrappingType = typeof(DelegatingEnumerable<,>).MakeGenericType(wrappedElementType, declaredElementType); diff --git a/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProviderFactory.cs b/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProviderFactory.cs index 99ab3c9c05..bc4471db58 100644 --- a/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProviderFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Xml/EnumerableWrapperProviderFactory.cs @@ -8,7 +8,7 @@ using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Mvc.Xml { /// - /// Creates an for interface types implementing the + /// Creates an for interface types implementing the /// type. /// public class EnumerableWrapperProviderFactory : IWrapperProviderFactory @@ -42,16 +42,16 @@ namespace Microsoft.AspNet.Mvc.Xml // concrete types like List, Collection which implement IEnumerable. if (declaredType != null && declaredType.IsInterface() && declaredType.IsGenericType()) { - var enumerableOfT = declaredType.ExtractGenericInterface(typeof(IEnumerable<>)); + var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface( + declaredType, + typeof(IEnumerable<>)); if (enumerableOfT != null) { - var elementType = enumerableOfT.GetGenericArguments()[0]; + var elementType = enumerableOfT.GenericTypeArguments[0]; + var wrapperProviderContext = new WrapperProviderContext(elementType, context.IsSerialization); - var wrapperProviderContext = new WrapperProviderContext( - elementType, - context.IsSerialization); - - var elementWrapperProvider = _wrapperProviderFactories.GetWrapperProvider(wrapperProviderContext); + var elementWrapperProvider = + _wrapperProviderFactories.GetWrapperProvider(wrapperProviderContext); return new EnumerableWrapperProvider(enumerableOfT, elementWrapperProvider); } diff --git a/src/Microsoft.AspNet.Mvc.Xml/RequiredValidationHelper.cs b/src/Microsoft.AspNet.Mvc.Xml/RequiredValidationHelper.cs index 0bf3d6e4c0..d03f8ed5f9 100644 --- a/src/Microsoft.AspNet.Mvc.Xml/RequiredValidationHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Xml/RequiredValidationHelper.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Xml { var visitedTypes = new HashSet(); - // Every node maintains a dictionary of Type => Errors. + // Every node maintains a dictionary of Type => Errors. // It's a dictionary as we want to avoid adding duplicate error messages. // Example: // In the following case, from the perspective of type 'Store', we should not see duplicate @@ -83,16 +83,16 @@ namespace Microsoft.AspNet.Mvc.Xml HashSet visitedTypes, Dictionary> errors) { - // We don't need to code special handling for KeyValuePair (for example, when the model type - // is Dictionary<,> which implements IEnumerable>) as the model + // We don't need to code special handling for KeyValuePair (for example, when the model type + // is Dictionary<,> which implements IEnumerable>) as the model // type here would be KeyValuePair where Key and Value are public properties // which would also be probed for Required attribute validation. if (modelType.IsGenericType()) { - var enumerableOfT = modelType.ExtractGenericInterface(typeof(IEnumerable<>)); + var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface(modelType, typeof(IEnumerable<>)); if (enumerableOfT != null) { - modelType = enumerableOfT.GetGenericArguments()[0]; + modelType = enumerableOfT.GenericTypeArguments[0]; } } @@ -143,10 +143,10 @@ namespace Microsoft.AspNet.Mvc.Xml typeof(DataMemberAttribute).FullName, nameof(DataMemberAttribute.IsRequired), bool.TrueString, - validationError.PropertyName, + validationError.PropertyName, validationError.ModelType.FullName)); } - + // if the type is not primitve, then it could be a struct in which case // we need to probe its properties for validation if (propertyType.GetTypeInfo().IsPrimitive) diff --git a/src/Microsoft.AspNet.Mvc.Xml/project.json b/src/Microsoft.AspNet.Mvc.Xml/project.json index d83632c700..1281914135 100644 --- a/src/Microsoft.AspNet.Mvc.Xml/project.json +++ b/src/Microsoft.AspNet.Mvc.Xml/project.json @@ -7,14 +7,15 @@ "dependencies": { "Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" }, "Microsoft.AspNet.Mvc.Core": "6.0.0-*", - "Microsoft.Framework.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" }, - "Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" } + "Microsoft.Framework.ClosedGenericMatcher.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" }, + "Microsoft.Framework.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" } }, "frameworks": { "dnx451": { "frameworkAssemblies": { - "System.Xml": "", - "System.Runtime.Serialization": "" + "System.Runtime.Serialization": "", + "System.Xml": "" } }, "dnxcore50": {