我已审核了some related questions和其他人。
我试图为System.Type创建一个扩展方法,并为System.Reflection.MethodBase创建一个伴随,以查找给定类型的所有扩展方法。
我有以下内容:
public static class MethodBaseExtensions
{
public static bool IsExtensionMethodForType(this MethodBase method, Type type)
{
if (1 > method.GetParameters().Count() || !method.IsDefined(typeof(ExtensionAttribute), false))
{
return false;
}
var extendedType = method.GetParameters().First().ParameterType;
if (!method.GetGenericArguments().Any(arg => arg.Equals(extendedType)))
{
if (extendedType.IsGenericType)
{
return extendedType.IsGenericTypeAssignableFrom(type);
}
return extendedType.IsAssignableFrom(type);
}
foreach (var constraint in extendedType.GetGenericParameterConstraints())
{
if (constraint.IsGenericType && !constraint.IsGenericTypeAssignableFrom(type))
{
return false;
}
if (!constraint.IsGenericType && !constraint.IsAssignableFrom(type))
{
return false;
}
}
return true;
}
}
用于:
public static class TypeExtensions
{
public static MethodInfo GetExtensionMethod(this Type type, string name)
{
return type.GetExtensionMethods().Single(m => m.Name.Equals(name, StringComparison.Ordinal));
}
public static IEnumerable<MethodInfo> GetExtensionMethods(this Type type)
{
return type.GetExtensionMethods(type.Assembly);
}
public static IEnumerable<MethodInfo> GetExtensionMethods(this Type type, Assembly assembly)
{
return type.GetExtensionMethods(new Assembly[] { assembly });
}
public static IEnumerable<MethodInfo> GetExtensionMethods(this Type type, IEnumerable<Assembly> assemblies)
{
const BindingFlags BINDING_FLAGS = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
return assemblies
.SelectMany(assembly => assembly.GetTypes().Where(t => t.IsExtensionMethodClass())
.SelectMany(t => t.GetMethods(BINDING_FLAGS))
.Where(m => m.IsExtensionMethodForType(type)));
}
public static bool IsGenericTypeAssignableFrom(this Type type, Type assignedType)
{
if (type.IsAssignableFrom(assignedType))
{
return true;
}
if (assignedType.IsGenericType &&
assignedType.GetGenericTypeDefinition().IsAssignableFrom(type))
{
return true;
}
foreach (var interfaceType in assignedType.GetInterfaces())
{
if (interfaceType.IsGenericType &&
interfaceType.GetGenericTypeDefinition().IsAssignableFrom(type))
{
return true;
}
}
if (default(Type) == assignedType.BaseType)
{
return false;
}
return type.IsGenericTypeAssignableFrom(assignedType.BaseType);
}
public static bool IsExtensionMethodClass(this Type type)
{
return type.IsSealed && !type.IsGenericType && !type.IsNested && type.IsDefined(typeof(ExtensionAttribute), false);
}
}
挑战是typeof(IFoo<>).GetExtensionMethods()
在
Test2
public static class IFooExtensions
{
public static void Test1(this IFoo<int> foo, int i)
{ }
public static void Test2<TFoo, T>(this TFoo foo, T t)
where TFoo : IFoo<T>
{ }
}
除非我调整MethodBaseExtensions.IsExtensionMethodForType
以获取两种类型的通用类型定义,最终使typeof(IFoo<string>).GetExtensionMethods()
也返回Test1
。
调试时,我发现IFoo<T>
和IFoo<>
都变为IFoo`1
,但他们显然是IFoo`1
的不同类型。
此时我正在寻找一个解决方案。
TIA