Skip to content

Commit

Permalink
Use Type everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
khellang committed Jan 28, 2022
1 parent 48e9002 commit 3ae8fa0
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 113 deletions.
4 changes: 1 addition & 3 deletions src/Scrutor/AttributeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? regis

foreach (var type in Types)
{
var typeInfo = type.GetTypeInfo();

var attributes = typeInfo.GetCustomAttributes<ServiceDescriptorAttribute>().ToArray();
var attributes = type.GetCustomAttributes<ServiceDescriptorAttribute>().ToArray();

// Check if the type has multiple attributes with same ServiceType.
var duplicates = GetDuplicates(attributes);
Expand Down
2 changes: 1 addition & 1 deletion src/Scrutor/IServiceTypeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public interface IServiceTypeSelector : IImplementationTypeSelector
/// Registers the type with the first found matching interface name. (e.g. ClassName is matched to IClassName)
/// </summary>
/// <param name="action">Filter for matching the Type to an implementing interface</param>
ILifetimeSelector AsMatchingInterface(Action<TypeInfo, IImplementationTypeFilter> action);
ILifetimeSelector AsMatchingInterface(Action<Type, IImplementationTypeFilter> action);

/// <summary>
/// Registers each matching concrete type as each of the types returned
Expand Down
2 changes: 1 addition & 1 deletion src/Scrutor/LifetimeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public ILifetimeSelector AsMatchingInterface()
return Inner.AsMatchingInterface();
}

public ILifetimeSelector AsMatchingInterface(Action<TypeInfo, IImplementationTypeFilter> action)
public ILifetimeSelector AsMatchingInterface(Action<Type, IImplementationTypeFilter> action)
{
return Inner.AsMatchingInterface(action);
}
Expand Down
148 changes: 61 additions & 87 deletions src/Scrutor/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,21 @@ internal static class ReflectionExtensions
{
public static bool IsNonAbstractClass(this Type type, bool publicOnly)
{
var typeInfo = type.GetTypeInfo();

if (typeInfo.IsSpecialName)
if (type.IsSpecialName)
{
return false;
}

if (typeInfo.IsClass && !typeInfo.IsAbstract)
if (type.IsClass && !type.IsAbstract)
{
if (typeInfo.IsDefined(typeof(CompilerGeneratedAttribute), inherit: true))
if (type.HasAttribute<CompilerGeneratedAttribute>())
{
return false;
}

if (publicOnly)
{
return typeInfo.IsPublic || typeInfo.IsNestedPublic;
return type.IsPublic || type.IsNestedPublic;
}

return true;
Expand All @@ -38,22 +36,16 @@ public static bool IsNonAbstractClass(this Type type, bool publicOnly)

public static IEnumerable<Type> GetBaseTypes(this Type type)
{
var typeInfo = type.GetTypeInfo();

foreach (var implementedInterface in typeInfo.ImplementedInterfaces)
foreach (var implementedInterface in type.GetInterfaces())
{
yield return implementedInterface;
}

var baseType = typeInfo.BaseType;

var baseType = type.BaseType;
while (baseType != null)
{
var baseTypeInfo = baseType.GetTypeInfo();

yield return baseType;

baseType = baseTypeInfo.BaseType;
baseType = baseType.BaseType;
}
}

Expand Down Expand Up @@ -90,131 +82,120 @@ public static bool IsInExactNamespace(this Type type, string @namespace)

public static bool HasAttribute(this Type type, Type attributeType)
{
return type.GetTypeInfo().IsDefined(attributeType, inherit: true);
return type.IsDefined(attributeType, inherit: true);
}

public static bool HasAttribute<T>(this Type type) where T : Attribute
{
return type.HasAttribute(typeof(T));
}

public static bool HasAttribute<T>(this Type type, Func<T, bool> predicate) where T : Attribute
{
return type.GetTypeInfo().GetCustomAttributes<T>(inherit: true).Any(predicate);
return type.GetCustomAttributes<T>(inherit: true).Any(predicate);
}

public static bool IsBasedOn(this Type type, Type otherType)
{
var typeInfo = type.GetTypeInfo();
var otherTypeInfo = otherType.GetTypeInfo();

if (otherTypeInfo.IsGenericTypeDefinition)
if (otherType.IsGenericTypeDefinition)
{
return typeInfo.IsAssignableToGenericTypeDefinition(otherTypeInfo);
return type.IsAssignableToGenericTypeDefinition(otherType);
}

return otherTypeInfo.IsAssignableFrom(typeInfo);
return otherType.IsAssignableFrom(type);
}

private static bool IsAssignableToGenericTypeDefinition(this TypeInfo typeInfo, TypeInfo genericTypeInfo)
private static bool IsAssignableToGenericTypeDefinition(this Type type, Type genericType)
{
var interfaceTypes = typeInfo.ImplementedInterfaces.Select(t => t.GetTypeInfo());

foreach (var interfaceType in interfaceTypes)
foreach (var interfaceType in type.GetInterfaces())
{
if (interfaceType.IsGenericType)
{
var typeDefinitionTypeInfo = interfaceType
.GetGenericTypeDefinition()
.GetTypeInfo();

if (typeDefinitionTypeInfo.Equals(genericTypeInfo))
var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();
if (genericTypeDefinition == genericType)
{
return true;
}
}
}

if (typeInfo.IsGenericType)
if (type.IsGenericType)
{
var typeDefinitionTypeInfo = typeInfo
.GetGenericTypeDefinition()
.GetTypeInfo();

if (typeDefinitionTypeInfo.Equals(genericTypeInfo))
var genericTypeDefinition = type.GetGenericTypeDefinition();
if (genericTypeDefinition == genericType)
{
return true;
}
}

var baseTypeInfo = typeInfo.BaseType?.GetTypeInfo();

if (baseTypeInfo is null)
var baseType = type.BaseType;
if (baseType is null)
{
return false;
}

return baseTypeInfo.IsAssignableToGenericTypeDefinition(genericTypeInfo);
return baseType.IsAssignableToGenericTypeDefinition(genericType);
}

/// <summary>
/// Find matching interface by name C# interface name convention. Optionally use a filter.
/// </summary>
/// <param name="typeInfo"></param>
/// <param name="action"></param>
/// <returns></returns>
public static IEnumerable<Type> FindMatchingInterface(this TypeInfo typeInfo, Action<TypeInfo, IImplementationTypeFilter>? action)
public static IEnumerable<Type> FindMatchingInterface(this Type type, Action<Type, IImplementationTypeFilter>? action)
{
var matchingInterfaceName = $"I{typeInfo.Name}";
var matchingInterfaceName = $"I{type.Name}";

var matchedInterfaces = GetImplementedInterfacesToMap(typeInfo)
var matchedInterfaces = GetImplementedInterfacesToMap(type)
.Where(x => string.Equals(x.Name, matchingInterfaceName, StringComparison.Ordinal))
.ToArray();

Type? type;
if (matchedInterfaces.Length == 0)
{
yield break;
}

Type? matchingType;
if (action is null)
{
type = matchedInterfaces.FirstOrDefault();
matchingType = matchedInterfaces.FirstOrDefault();
}
else
{
var filter = new ImplementationTypeFilter(matchedInterfaces);

action(typeInfo, filter);
action(type, filter);

type = filter.Types.FirstOrDefault();
matchingType = filter.Types.FirstOrDefault();
}

if (type is null)
if (matchingType is null)
{
yield break;
}

yield return type;
yield return matchingType;
}

private static IEnumerable<Type> GetImplementedInterfacesToMap(TypeInfo typeInfo)
private static IEnumerable<Type> GetImplementedInterfacesToMap(Type type)
{
if (!typeInfo.IsGenericType)
if (!type.IsGenericType)
{
return typeInfo.ImplementedInterfaces;
return type.GetInterfaces();
}

if (!typeInfo.IsGenericTypeDefinition)
if (!type.IsGenericTypeDefinition)
{
return typeInfo.ImplementedInterfaces;
return type.GetInterfaces();
}

return FilterMatchingGenericInterfaces(typeInfo);
return FilterMatchingGenericInterfaces(type);
}

private static IEnumerable<Type> FilterMatchingGenericInterfaces(TypeInfo typeInfo)
private static IEnumerable<Type> FilterMatchingGenericInterfaces(Type type)
{
var genericTypeParameters = typeInfo.GenericTypeParameters;
var genericArguments = type.GetGenericArguments();

foreach (var current in typeInfo.ImplementedInterfaces)
foreach (var current in type.GetInterfaces())
{
var currentTypeInfo = current.GetTypeInfo();

if (currentTypeInfo.IsGenericType && currentTypeInfo.ContainsGenericParameters
&& GenericParametersMatch(genericTypeParameters, currentTypeInfo.GenericTypeArguments))
if (current.IsGenericType && current.ContainsGenericParameters && GenericParametersMatch(genericArguments, current.GetGenericArguments()))
{
yield return currentTypeInfo.GetGenericTypeDefinition();
yield return current.GetGenericTypeDefinition();
}
}
}
Expand Down Expand Up @@ -244,19 +225,17 @@ public static string ToFriendlyName(this Type type)

public static bool IsOpenGeneric(this Type type)
{
return type.GetTypeInfo().IsGenericTypeDefinition;
return type.IsGenericTypeDefinition;
}

public static bool HasMatchingGenericArity(this Type interfaceType, TypeInfo typeInfo)
public static bool HasMatchingGenericArity(this Type interfaceType, Type type)
{
if (typeInfo.IsGenericType)
if (type.IsGenericType)
{
var interfaceTypeInfo = interfaceType.GetTypeInfo();

if (interfaceTypeInfo.IsGenericType)
if (interfaceType.IsGenericType)
{
var argumentCount = interfaceType.GenericTypeArguments.Length;
var parameterCount = typeInfo.GenericTypeParameters.Length;
var argumentCount = interfaceType.GetGenericArguments().Length;
var parameterCount = type.GetGenericArguments().Length;

return argumentCount == parameterCount;
}
Expand All @@ -267,16 +246,11 @@ public static bool HasMatchingGenericArity(this Type interfaceType, TypeInfo typ
return true;
}

public static Type GetRegistrationType(this Type interfaceType, TypeInfo typeInfo)
public static Type GetRegistrationType(this Type interfaceType, Type type)
{
if (typeInfo.IsGenericTypeDefinition)
if (type.IsGenericTypeDefinition && interfaceType.IsGenericType)
{
var interfaceTypeInfo = interfaceType.GetTypeInfo();

if (interfaceTypeInfo.IsGenericType)
{
return interfaceType.GetGenericTypeDefinition();
}
return interfaceType.GetGenericTypeDefinition();
}

return interfaceType;
Expand Down
2 changes: 1 addition & 1 deletion src/Scrutor/ServiceCollectionExtensions.Decoration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private static bool TryDecorateOpenGeneric(this IServiceCollection services, Typ

foreach (var closedGenericServiceType in closedGenericServiceTypes)
{
var arguments = closedGenericServiceType.GenericTypeArguments;
var arguments = closedGenericServiceType.GetGenericArguments();

var closedServiceType = serviceType.MakeGenericType(arguments);
try
Expand Down
23 changes: 9 additions & 14 deletions src/Scrutor/ServiceTypeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 +49,40 @@ public ILifetimeSelector As(IEnumerable<Type> types)

public ILifetimeSelector AsImplementedInterfaces()
{
return AsTypeInfo(t => t.ImplementedInterfaces
return As(t => t.GetInterfaces()
.Where(x => x.HasMatchingGenericArity(t))
.Select(x => x.GetRegistrationType(t)));
}

public ILifetimeSelector AsSelfWithInterfaces()
{
IEnumerable<Type> Selector(TypeInfo info)
IEnumerable<Type> Selector(Type type)
{
if (info.IsGenericTypeDefinition)
if (type.IsGenericTypeDefinition)
{
// This prevents trying to register open generic types
// with an ImplementationFactory, which is unsupported.
return Enumerable.Empty<Type>();
}

return info.ImplementedInterfaces
.Where(x => x.HasMatchingGenericArity(info))
.Select(x => x.GetRegistrationType(info));
return type.GetInterfaces()
.Where(x => x.HasMatchingGenericArity(type))
.Select(x => x.GetRegistrationType(type));
}

return AddSelector(
Types.Select(t => new TypeMap(t, new[] { t })),
Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t.GetTypeInfo()))));
Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t))));
}

public ILifetimeSelector AsMatchingInterface()
{
return AsMatchingInterface(null);
}

public ILifetimeSelector AsMatchingInterface(Action<TypeInfo, IImplementationTypeFilter>? action)
public ILifetimeSelector AsMatchingInterface(Action<Type, IImplementationTypeFilter>? action)
{
return AsTypeInfo(t => t.FindMatchingInterface(action));
return As(t => t.FindMatchingInterface(action));
}

public ILifetimeSelector As(Func<Type, IEnumerable<Type>> selector)
Expand Down Expand Up @@ -229,10 +229,5 @@ private ILifetimeSelector AddSelector(IEnumerable<TypeMap> types, IEnumerable<Ty

return selector;
}

private ILifetimeSelector AsTypeInfo(Func<TypeInfo, IEnumerable<Type>> selector)
{
return As(t => selector(t.GetTypeInfo()));
}
}
}
Loading

0 comments on commit 3ae8fa0

Please sign in to comment.