Use `ClosedGenericMatcher.ExtractGenericInterface()` from Common repo

- added in aspnet/Common@aae8e6e

nits:
- reorder dependencies alphabetically
- avoid `GetGenericArguments()` extension method with `ExtractGenericInterface()` return value
 - use `GenericTypeArguments`
- usual trailing whitespace auto-removals
This commit is contained in:
Doug Bunting 2015-05-08 17:13:38 -07:00
parent 583277cceb
commit 61b76fd99f
12 changed files with 61 additions and 54 deletions

View File

@ -45,15 +45,6 @@ namespace Microsoft.AspNet.Mvc
return type.GetTypeInfo().BaseType; return type.GetTypeInfo().BaseType;
} }
public static Type ExtractGenericInterface([NotNull] this Type queryType, Type interfaceType)
{
Func<Type, bool> matchesInterface =
t => t.IsGenericType() && t.GetGenericTypeDefinition() == interfaceType;
return (matchesInterface(queryType)) ?
queryType :
queryType.GetInterfaces().FirstOrDefault(matchesInterface);
}
#if NETFX_CORE || DNXCORE50 #if NETFX_CORE || DNXCORE50
public static Type[] GetGenericArguments([NotNull] this Type type) public static Type[] GetGenericArguments([NotNull] this Type type)
{ {

View File

@ -151,8 +151,9 @@ namespace Microsoft.AspNet.Mvc
} }
// Determine T if this is an ICollection<T> property. // Determine T if this is an ICollection<T> property.
var collectionTypeArguments = propertyType var collectionTypeArguments = ClosedGenericMatcher.ExtractGenericInterface(
.ExtractGenericInterface(typeof(ICollection<>)) propertyType,
typeof(ICollection<>))
?.GenericTypeArguments; ?.GenericTypeArguments;
if (collectionTypeArguments == null) if (collectionTypeArguments == null)
{ {

View File

@ -555,8 +555,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Determine T if this is an ICollection<T> property. No need for a T[] case because CanUpdateProperty() // Determine T if this is an ICollection<T> property. No need for a T[] case because CanUpdateProperty()
// ensures property is either settable or not an array. Underlying assumption is that CanUpdateProperty() // ensures property is either settable or not an array. Underlying assumption is that CanUpdateProperty()
// and SetProperty() are overridden together. // and SetProperty() are overridden together.
var collectionTypeArguments = propertyExplorer.ModelType var collectionTypeArguments = ClosedGenericMatcher.ExtractGenericInterface(
.ExtractGenericInterface(typeof(ICollection<>)) propertyExplorer.ModelType,
typeof(ICollection<>))
?.GenericTypeArguments; ?.GenericTypeArguments;
if (collectionTypeArguments == null) if (collectionTypeArguments == null)
{ {

View File

@ -38,13 +38,13 @@ namespace Microsoft.AspNet.Mvc.Rendering.Expressions
_tryGetValueDelegateCacheLock.ExitReadLock(); _tryGetValueDelegateCacheLock.ExitReadLock();
} }
var dictionaryType = targetType.ExtractGenericInterface(typeof(IDictionary<,>)); var dictionaryType = ClosedGenericMatcher.ExtractGenericInterface(targetType, typeof(IDictionary<,>));
// Just wrap a call to the underlying IDictionary<TKey, TValue>.TryGetValue() where string can be cast to // Just wrap a call to the underlying IDictionary<TKey, TValue>.TryGetValue() where string can be cast to
// TKey. // TKey.
if (dictionaryType != null) if (dictionaryType != null)
{ {
var typeArguments = dictionaryType.GetGenericArguments(); var typeArguments = dictionaryType.GenericTypeArguments;
var keyType = typeArguments[0]; var keyType = typeArguments[0];
var returnType = typeArguments[1]; var returnType = typeArguments[1];

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering.Internal; using Microsoft.AspNet.Mvc.Rendering.Internal;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.Rendering namespace Microsoft.AspNet.Mvc.Rendering
{ {
@ -106,10 +107,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
var typeInCollection = typeof(string); var typeInCollection = typeof(string);
var genericEnumerableType = collection.GetType().ExtractGenericInterface(typeof(IEnumerable<>)); var genericEnumerableType = ClosedGenericMatcher.ExtractGenericInterface(
collection.GetType(),
typeof(IEnumerable<>));
if (genericEnumerableType != null) if (genericEnumerableType != null)
{ {
typeInCollection = genericEnumerableType.GetGenericArguments()[0]; typeInCollection = genericEnumerableType.GenericTypeArguments[0];
} }
var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType(); var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType();

View File

@ -68,10 +68,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
} }
var typeInCollection = typeof(string); var typeInCollection = typeof(string);
var genericEnumerableType = collection.GetType().ExtractGenericInterface(typeof(IEnumerable<>)); var genericEnumerableType = ClosedGenericMatcher.ExtractGenericInterface(
collection.GetType(),
typeof(IEnumerable<>));
if (genericEnumerableType != null) if (genericEnumerableType != null)
{ {
typeInCollection = genericEnumerableType.GetGenericArguments()[0]; typeInCollection = genericEnumerableType.GenericTypeArguments[0];
} }
var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType(); var typeInCollectionIsNullableValueType = typeInCollection.IsNullableValueType();

View File

@ -159,12 +159,14 @@ namespace Microsoft.AspNet.Mvc
// Accessing Session property will throw if the session middleware is not enabled. // Accessing Session property will throw if the session middleware is not enabled.
var session = context.Session; var session = context.Session;
using (var memoryStream = new MemoryStream()) using (var memoryStream = new MemoryStream())
using (var writer = new BsonWriter(memoryStream))
{ {
_jsonSerializer.Serialize(writer, values); using (var writer = new BsonWriter(memoryStream))
session[TempDataSessionStateKey] = memoryStream.ToArray(); {
_jsonSerializer.Serialize(writer, values);
session[TempDataSessionStateKey] = memoryStream.ToArray();
}
} }
} }
else if (IsSessionEnabled(context)) else if (IsSessionEnabled(context))
@ -190,16 +192,19 @@ namespace Microsoft.AspNet.Mvc
} }
else if (itemType.GetTypeInfo().IsGenericType) 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<T> has one generic argument"); Debug.Assert(genericTypeArguments.Length == 1, "IList<T> has one generic argument");
actualType = genericTypeArguments[0]; actualType = genericTypeArguments[0];
} }
else if (itemType.ExtractGenericInterface(typeof(IDictionary<,>)) != null) else if (ClosedGenericMatcher.ExtractGenericInterface(itemType, typeof(IDictionary<,>)) != null)
{ {
var genericTypeArguments = itemType.GetGenericArguments(); var genericTypeArguments = itemType.GenericTypeArguments;
Debug.Assert(genericTypeArguments.Length == 2, "IDictionary<TKey, TValue> has two generic arguments"); Debug.Assert(
genericTypeArguments.Length == 2,
"IDictionary<TKey, TValue> has two generic arguments");
// Throw if the key type of the dictionary is not string. // Throw if the key type of the dictionary is not string.
if (genericTypeArguments[0] != typeof(string)) if (genericTypeArguments[0] != typeof(string))
{ {

View File

@ -13,18 +13,19 @@
"Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*",
"Microsoft.AspNet.Hosting.Abstractions": "1.0.0-*", "Microsoft.AspNet.Hosting.Abstractions": "1.0.0-*",
"Microsoft.AspNet.Http.Extensions": "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.Abstractions": "6.0.0-*",
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" }, "Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Routing": "1.0.0-*", "Microsoft.AspNet.Routing": "1.0.0-*",
"Microsoft.Framework.BufferEntryCollection.Sources": { "version": "1.0.0-*", "type": "build" }, "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.CopyOnWriteDictionary.Sources": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.Logging.Abstractions": "1.0.0-*", "Microsoft.Framework.Logging.Abstractions": "1.0.0-*",
"Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" }, "Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.PropertyActivator.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.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.Runtime.Abstractions": "1.0.0-*", "Microsoft.Framework.Runtime.Abstractions": "1.0.0-*",
"Microsoft.Framework.WebEncoders": "1.0.0-*", "Microsoft.Framework.WebEncoders": "1.0.0-*"
"Microsoft.AspNet.JsonPatch": "1.0.0-*"
}, },
"frameworks": { "frameworks": {
"dnx451": { "dnx451": {

View File

@ -9,7 +9,7 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.Xml namespace Microsoft.AspNet.Mvc.Xml
{ {
/// <summary> /// <summary>
/// Provides a <see cref="IWrapperProvider"/> for interface types which implement /// Provides a <see cref="IWrapperProvider"/> for interface types which implement
/// <see cref="IEnumerable{T}"/>. /// <see cref="IEnumerable{T}"/>.
/// </summary> /// </summary>
public class EnumerableWrapperProvider : IWrapperProvider public class EnumerableWrapperProvider : IWrapperProvider
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Xml
/// <summary> /// <summary>
/// Initializes an instance of <see cref="EnumerableWrapperProvider"/>. /// Initializes an instance of <see cref="EnumerableWrapperProvider"/>.
/// </summary> /// </summary>
/// <param name="sourceEnumerableOfT">Type of the original <see cref="IEnumerable{T}" /> /// <param name="sourceEnumerableOfT">Type of the original <see cref="IEnumerable{T}" />
/// that is being wrapped.</param> /// that is being wrapped.</param>
/// <param name="elementWrapperProvider">The <see cref="IWrapperProvider"/> for the element type. /// <param name="elementWrapperProvider">The <see cref="IWrapperProvider"/> for the element type.
/// Can be null.</param> /// Can be null.</param>
@ -28,17 +28,19 @@ namespace Microsoft.AspNet.Mvc.Xml
[NotNull] Type sourceEnumerableOfT, [NotNull] Type sourceEnumerableOfT,
IWrapperProvider elementWrapperProvider) IWrapperProvider elementWrapperProvider)
{ {
var enumerableOfT = sourceEnumerableOfT.ExtractGenericInterface(typeof(IEnumerable<>)); var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface(
sourceEnumerableOfT,
typeof(IEnumerable<>));
if (!sourceEnumerableOfT.IsInterface() || enumerableOfT == null) if (!sourceEnumerableOfT.IsInterface() || enumerableOfT == null)
{ {
throw new ArgumentException( throw new ArgumentException(
Resources.FormatEnumerableWrapperProvider_InvalidSourceEnumerableOfT(typeof(IEnumerable<>).Name), Resources.FormatEnumerableWrapperProvider_InvalidSourceEnumerableOfT(typeof(IEnumerable<>).Name),
nameof(sourceEnumerableOfT)); nameof(sourceEnumerableOfT));
} }
_wrapperProvider = elementWrapperProvider; _wrapperProvider = elementWrapperProvider;
var declaredElementType = enumerableOfT.GetGenericArguments()[0]; var declaredElementType = enumerableOfT.GenericTypeArguments[0];
var wrappedElementType = elementWrapperProvider?.WrappingType ?? declaredElementType; var wrappedElementType = elementWrapperProvider?.WrappingType ?? declaredElementType;
WrappingType = typeof(DelegatingEnumerable<,>).MakeGenericType(wrappedElementType, declaredElementType); WrappingType = typeof(DelegatingEnumerable<,>).MakeGenericType(wrappedElementType, declaredElementType);

View File

@ -8,7 +8,7 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.Xml namespace Microsoft.AspNet.Mvc.Xml
{ {
/// <summary> /// <summary>
/// Creates an <see cref="EnumerableWrapperProvider"/> for interface types implementing the /// Creates an <see cref="EnumerableWrapperProvider"/> for interface types implementing the
/// <see cref="IEnumerable{T}"/> type. /// <see cref="IEnumerable{T}"/> type.
/// </summary> /// </summary>
public class EnumerableWrapperProviderFactory : IWrapperProviderFactory public class EnumerableWrapperProviderFactory : IWrapperProviderFactory
@ -42,16 +42,16 @@ namespace Microsoft.AspNet.Mvc.Xml
// concrete types like List<T>, Collection<T> which implement IEnumerable<T>. // concrete types like List<T>, Collection<T> which implement IEnumerable<T>.
if (declaredType != null && declaredType.IsInterface() && declaredType.IsGenericType()) if (declaredType != null && declaredType.IsInterface() && declaredType.IsGenericType())
{ {
var enumerableOfT = declaredType.ExtractGenericInterface(typeof(IEnumerable<>)); var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface(
declaredType,
typeof(IEnumerable<>));
if (enumerableOfT != null) if (enumerableOfT != null)
{ {
var elementType = enumerableOfT.GetGenericArguments()[0]; var elementType = enumerableOfT.GenericTypeArguments[0];
var wrapperProviderContext = new WrapperProviderContext(elementType, context.IsSerialization);
var wrapperProviderContext = new WrapperProviderContext( var elementWrapperProvider =
elementType, _wrapperProviderFactories.GetWrapperProvider(wrapperProviderContext);
context.IsSerialization);
var elementWrapperProvider = _wrapperProviderFactories.GetWrapperProvider(wrapperProviderContext);
return new EnumerableWrapperProvider(enumerableOfT, elementWrapperProvider); return new EnumerableWrapperProvider(enumerableOfT, elementWrapperProvider);
} }

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Xml
{ {
var visitedTypes = new HashSet<Type>(); var visitedTypes = new HashSet<Type>();
// 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. // It's a dictionary as we want to avoid adding duplicate error messages.
// Example: // Example:
// In the following case, from the perspective of type 'Store', we should not see duplicate // 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<Type> visitedTypes, HashSet<Type> visitedTypes,
Dictionary<Type, List<string>> errors) Dictionary<Type, List<string>> errors)
{ {
// We don't need to code special handling for KeyValuePair (for example, when the model type // We don't need to code special handling for KeyValuePair (for example, when the model type
// is Dictionary<,> which implements IEnumerable<KeyValuePair<TKey, TValue>>) as the model // is Dictionary<,> which implements IEnumerable<KeyValuePair<TKey, TValue>>) as the model
// type here would be KeyValuePair<TKey, TValue> where Key and Value are public properties // type here would be KeyValuePair<TKey, TValue> where Key and Value are public properties
// which would also be probed for Required attribute validation. // which would also be probed for Required attribute validation.
if (modelType.IsGenericType()) if (modelType.IsGenericType())
{ {
var enumerableOfT = modelType.ExtractGenericInterface(typeof(IEnumerable<>)); var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface(modelType, typeof(IEnumerable<>));
if (enumerableOfT != null) if (enumerableOfT != null)
{ {
modelType = enumerableOfT.GetGenericArguments()[0]; modelType = enumerableOfT.GenericTypeArguments[0];
} }
} }
@ -143,10 +143,10 @@ namespace Microsoft.AspNet.Mvc.Xml
typeof(DataMemberAttribute).FullName, typeof(DataMemberAttribute).FullName,
nameof(DataMemberAttribute.IsRequired), nameof(DataMemberAttribute.IsRequired),
bool.TrueString, bool.TrueString,
validationError.PropertyName, validationError.PropertyName,
validationError.ModelType.FullName)); validationError.ModelType.FullName));
} }
// if the type is not primitve, then it could be a struct in which case // if the type is not primitve, then it could be a struct in which case
// we need to probe its properties for validation // we need to probe its properties for validation
if (propertyType.GetTypeInfo().IsPrimitive) if (propertyType.GetTypeInfo().IsPrimitive)

View File

@ -7,14 +7,15 @@
"dependencies": { "dependencies": {
"Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" }, "Microsoft.AspNet.Mvc.Common": { "version": "6.0.0-*", "type": "build" },
"Microsoft.AspNet.Mvc.Core": "6.0.0-*", "Microsoft.AspNet.Mvc.Core": "6.0.0-*",
"Microsoft.Framework.PropertyHelper.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.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" },
"Microsoft.Framework.PropertyHelper.Sources": { "version": "1.0.0-*", "type": "build" }
}, },
"frameworks": { "frameworks": {
"dnx451": { "dnx451": {
"frameworkAssemblies": { "frameworkAssemblies": {
"System.Xml": "", "System.Runtime.Serialization": "",
"System.Runtime.Serialization": "" "System.Xml": ""
} }
}, },
"dnxcore50": { "dnxcore50": {