Skip to content

Commit

Permalink
Code cleanup to make some of the nested if/else easier to read.
Browse files Browse the repository at this point in the history
  • Loading branch information
Travis Illig committed Sep 13, 2016
1 parent 1f1ae09 commit 41044d7
Showing 1 changed file with 78 additions and 66 deletions.
144 changes: 78 additions & 66 deletions src/Autofac/Util/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,18 @@ namespace Autofac.Util
internal static class TypeExtensions
{
private static readonly ConcurrentDictionary<Type, bool> IsGenericEnumerableInterfaceCache = new ConcurrentDictionary<Type, bool>();

private static readonly ConcurrentDictionary<Type, bool> IsGenericListOrCollectionInterfaceTypeCache = new ConcurrentDictionary<Type, bool>();

private static readonly ConcurrentDictionary<Tuple<Type, Type>, bool> IsGenericTypeDefinedByCache = new ConcurrentDictionary<Tuple<Type, Type>, bool>();

public static Type FunctionReturnType(this Type type)
{
var invoke = type.GetTypeInfo().GetDeclaredMethod("Invoke");
Enforce.NotNull(invoke);
return invoke.ReturnType;
}

/// <summary>Returns the first concrete interface supported by the candidate type that
/// closes the provided open generic service type.</summary>
/// <param name="this">The type that is being checked for the interface.</param>
Expand All @@ -49,93 +58,108 @@ public static IEnumerable<Type> GetTypesThatClose(this Type @this, Type openGene
return FindAssignableTypesThatClose(@this, openGeneric);
}

/// <summary>
/// Looks for an interface on the candidate type that closes the provided open generic interface type.
/// </summary>
/// <param name="candidateType">The type that is being checked for the interface.</param>
/// <param name="openGenericServiceType">The open generic service type to locate.</param>
/// <returns>True if a closed implementation was found; otherwise false.</returns>
private static IEnumerable<Type> FindAssignableTypesThatClose(Type candidateType, Type openGenericServiceType)
{
return TypesAssignableFrom(candidateType)
.Where(t => t.IsClosedTypeOf(openGenericServiceType));
}

private static IEnumerable<Type> TypesAssignableFrom(Type candidateType)
{
return candidateType.GetTypeInfo().ImplementedInterfaces.Concat(
Traverse.Across(candidateType, t => t.GetTypeInfo().BaseType));
}

public static bool IsGenericTypeDefinedBy(this Type @this, Type openGeneric)
{
return IsGenericTypeDefinedByCache.GetOrAdd(
Tuple.Create(@this, openGeneric),
key => !key.Item1.GetTypeInfo().ContainsGenericParameters
&& key.Item1.GetTypeInfo().IsGenericType
&& key.Item1.GetGenericTypeDefinition() == key.Item2);
}

public static bool IsClosedTypeOf(this Type @this, Type openGeneric)
{
return TypesAssignableFrom(@this).Any(t => t.GetTypeInfo().IsGenericType && !@this.GetTypeInfo().ContainsGenericParameters && t.GetGenericTypeDefinition() == openGeneric);
}

public static bool IsDelegate(this Type type)
{
return type.GetTypeInfo().IsSubclassOf(typeof(Delegate));
}

public static Type FunctionReturnType(this Type type)
{
var invoke = type.GetTypeInfo().GetDeclaredMethod("Invoke");
Enforce.NotNull(invoke);
return invoke.ReturnType;
}

public static bool IsCompatibleWithGenericParameterConstraints(this Type genericTypeDefinition, Type[] parameters)
{
var genericArgumentDefinitions = genericTypeDefinition.GetTypeInfo().GenericTypeParameters;

for (var i = 0; i < genericArgumentDefinitions.Length; ++i)
{
var argumentDefinition = genericArgumentDefinitions[i];
var argumentDefinitionTypeInfo = genericArgumentDefinitions[i].GetTypeInfo();
var parameter = parameters[i];
var parameterTypeInfo = parameter.GetTypeInfo();

if (argumentDefinition.GetTypeInfo().GetGenericParameterConstraints()
if (argumentDefinitionTypeInfo.GetGenericParameterConstraints()
.Any(constraint => !ParameterCompatibleWithTypeConstraint(parameter, constraint)))
{
return false;
}

var specialConstraints = argumentDefinition.GetTypeInfo().GenericParameterAttributes;
var specialConstraints = argumentDefinitionTypeInfo.GenericParameterAttributes;

if ((specialConstraints & GenericParameterAttributes.DefaultConstructorConstraint)
!= GenericParameterAttributes.None)
{
if (!parameter.GetTypeInfo().IsValueType && parameter.GetTypeInfo().DeclaredConstructors.All(c => c.GetParameters().Count() != 0))
if (!parameterTypeInfo.IsValueType && parameterTypeInfo.DeclaredConstructors.All(c => c.GetParameters().Count() != 0))
{
return false;
}
}

if ((specialConstraints & GenericParameterAttributes.ReferenceTypeConstraint)
!= GenericParameterAttributes.None)
{
if (parameter.GetTypeInfo().IsValueType)
if (parameterTypeInfo.IsValueType)
{
return false;
}
}

if ((specialConstraints & GenericParameterAttributes.NotNullableValueTypeConstraint)
!= GenericParameterAttributes.None)
{
if (!parameter.GetTypeInfo().IsValueType ||
(parameter.GetTypeInfo().IsGenericType && IsGenericTypeDefinedBy(parameter, typeof(Nullable<>))))
if (!parameterTypeInfo.IsValueType ||
(parameterTypeInfo.IsGenericType && IsGenericTypeDefinedBy(parameter, typeof(Nullable<>))))
{
return false;
}
}
}

return true;
}

public static bool IsCompilerGenerated(this Type type)
{
return type.GetTypeInfo().GetCustomAttributes<CompilerGeneratedAttribute>().Any();
}

public static bool IsDelegate(this Type type)
{
return type.GetTypeInfo().IsSubclassOf(typeof(Delegate));
}

public static bool IsGenericEnumerableInterfaceType(this Type type)
{
return IsGenericEnumerableInterfaceCache.GetOrAdd(
type, t => type.IsGenericTypeDefinedBy(typeof(IEnumerable<>))
|| type.IsGenericListOrCollectionInterfaceType());
}

public static bool IsGenericListOrCollectionInterfaceType(this Type type)
{
return IsGenericListOrCollectionInterfaceTypeCache.GetOrAdd(
type, t => t.IsGenericTypeDefinedBy(typeof(IList<>))
|| t.IsGenericTypeDefinedBy(typeof(ICollection<>))
|| t.IsGenericTypeDefinedBy(typeof(IReadOnlyCollection<>))
|| t.IsGenericTypeDefinedBy(typeof(IReadOnlyList<>)));
}

public static bool IsGenericTypeDefinedBy(this Type @this, Type openGeneric)
{
return IsGenericTypeDefinedByCache.GetOrAdd(
Tuple.Create(@this, openGeneric),
key => !key.Item1.GetTypeInfo().ContainsGenericParameters
&& key.Item1.GetTypeInfo().IsGenericType
&& key.Item1.GetGenericTypeDefinition() == key.Item2);
}

/// <summary>
/// Looks for an interface on the candidate type that closes the provided open generic interface type.
/// </summary>
/// <param name="candidateType">The type that is being checked for the interface.</param>
/// <param name="openGenericServiceType">The open generic service type to locate.</param>
/// <returns>True if a closed implementation was found; otherwise false.</returns>
private static IEnumerable<Type> FindAssignableTypesThatClose(Type candidateType, Type openGenericServiceType)
{
return TypesAssignableFrom(candidateType)
.Where(t => t.IsClosedTypeOf(openGenericServiceType));
}

private static bool ParameterCompatibleWithTypeConstraint(Type parameter, Type constraint)
{
return constraint.GetTypeInfo().IsAssignableFrom(parameter.GetTypeInfo()) ||
Expand All @@ -158,10 +182,13 @@ private static bool ParameterEqualsConstraint(Type parameter, Type constraint)
var genericType = typeDefinition.MakeGenericType(genericArguments);
var constraintArguments = constraint.GetTypeInfo().GenericTypeArguments;

for (int i = 0; i < constraintArguments.Count(); i++)
for (var i = 0; i < constraintArguments.Length; i++)
{
var constraintArgument = constraintArguments[i].GetTypeInfo();
if (!constraintArgument.IsGenericParameter && !constraintArgument.IsAssignableFrom(genericArguments[i].GetTypeInfo())) return false;
if (!constraintArgument.IsGenericParameter && !constraintArgument.IsAssignableFrom(genericArguments[i].GetTypeInfo()))
{
return false;
}
}

return genericType == parameter;
Expand All @@ -176,25 +203,10 @@ private static bool ParameterEqualsConstraint(Type parameter, Type constraint)
return false;
}

public static bool IsGenericEnumerableInterfaceType(this Type type)
{
return IsGenericEnumerableInterfaceCache.GetOrAdd(
type, t => type.IsGenericTypeDefinedBy(typeof(IEnumerable<>))
|| type.IsGenericListOrCollectionInterfaceType());
}

public static bool IsGenericListOrCollectionInterfaceType(this Type type)
{
return IsGenericListOrCollectionInterfaceTypeCache.GetOrAdd(
type, t => t.IsGenericTypeDefinedBy(typeof(IList<>))
|| t.IsGenericTypeDefinedBy(typeof(ICollection<>))
|| t.IsGenericTypeDefinedBy(typeof(IReadOnlyCollection<>))
|| t.IsGenericTypeDefinedBy(typeof(IReadOnlyList<>)));
}

public static bool IsCompilerGenerated(this Type type)
private static IEnumerable<Type> TypesAssignableFrom(Type candidateType)
{
return type.GetTypeInfo().GetCustomAttributes<CompilerGeneratedAttribute>().Any();
return candidateType.GetTypeInfo().ImplementedInterfaces.Concat(
Traverse.Across(candidateType, t => t.GetTypeInfo().BaseType));
}
}
}

0 comments on commit 41044d7

Please sign in to comment.