我将首先链接this question,它显示了一种方法来做我想做的事情 - 不幸的是,它在.Net Standard 1.1中是不可能的。
虽然我需要这个适用于任何泛型类型,但这是一个示例类型:
class MyGeneric<T>
{
public MyGeneric(T a1, string a2) { }
public MyGeneric(T a1, double a2) { }
}
我想要一个函数,当提供ConstructorInfo
具体 MyGeneric<>
时,例如:
MyGeneric<int>..ctor(int, double)
将为同一个构造函数返回另一个ConstructorInfo
,但是对于未绑定的泛型类型MyGeneric<>
而言:
MyGeneric<T>..ctor(T, double)
然后,目的是能够采用另一种方式 - 即给定
MyGeneric<T>..ctor(T, double)
,我可以获得该通用的任何绑定/封闭版本的相同构造函数 - 例如MyGeneric<DateTime>..ctor(DateTime, double)
或MyGeneric<Foo>..ctor(Foo, double)
。当泛型类型参数在构造函数签名中作为另一个泛型的类型参数出现时,它也必须工作 - 例如
MyGeneric(IEnumerable<T>)
我能找到的最佳实现是上面的链接,它使用MethodBase.GetMethodFromHandle(RuntimeMethodHandle, RuntimeTypeHandle)
:
return (ConstructorInfo)MethodBase.GetMethodFromHandle(
ctor.MethodHandle,
ctor.DeclaringType.GetGenericTypeDefinition().TypeHandle);
(假设ctor
包含对具体泛型类型的构造函数版本的引用)
这适用于所有类型的所有构造函数,无论泛型类型自身类型参数与构造函数参数类型之间的关系有多古怪。
但是,虽然.netstandard1.1 确实具有MethodBase.GetMethodFromHandle
静态方法,但似乎没有办法从{{1}获取RuntimeMethodHandle
对象(即MethodInfo
基类MethodHandle
上没有MethodBase
属性。
所以我觉得这样做是不可能的。
目前,我对.Net Standard 1.1的实现假定Constructorinfo
(或Type
)为开放式通用返回的成员顺序与任何已关闭的通用内容返回的成员顺序相同从它:
TypeInfo
注意:var position = Array.IndexOf(
TypeHelpers.GetConstructors(ctor.DeclaringType),
ctor);
if(position >= 0)
{
return TypeHelpers.GetConstructors(
ctor.DeclaringType.GetGenericTypeDefinition())[position];
}
方法仅根据目标框架使用旧的或更新的反射API返回类型的公共构造函数
一旦我知道了索引,然后我重新使用它来从开放泛型的构造函数映射回到封闭的构造函数,用于从该开放泛型构建的任何闭合/绑定泛型。
这似乎有用( 有警告,请参阅下一页 ),有点有意义(因为所有具体的泛型应该逻辑上'继承' '所有字段/方法元数据按相同顺序列出) - 但感觉不对,因为我们永远依赖于从任何反射API返回的结果的顺序。
注意事项
上述基于TypeHelpers.GetConstructors
的解决方案间歇性地 ,因为每当使用TypeInfo
API时,它都依赖于ConstructorInfo
缓存,因此您可以比较引用相等性构造函数。但结果并非总是如此!
有更好的方法吗?是否可以从.NetStandard 1.1中的DeclaredConstructors
获取RuntimeMethodHandle
或RuntimeTypeHandle
- 或者我是否应该像第二个代码示例一样搜索方法/构造函数的数组?
看起来很奇怪.NetStandard 1.1有ConstructorInfo
重载,但似乎没有提供任何方法来获取你需要的句柄作为参数!
答案 0 :(得分:0)
我仍处于核心反思的学习曲线上,但请看下面的例子,看看它是否有帮助。
//assumes ctor contains a reference to the
//concrete generic type's version of the constructor
public Type GetDeclaringType(ConstructorInfo ctor) {
var type = ctor.DeclaringType;//Gets the class that declares this member.
var typeInfo = type.GetTypeInfo();//Returns TypeInfo representation of specified type.
if (typeInfo.IsGenericType) {
type = typeInfo.GetGenericTypeDefinition();
}
return type;
}
所以假设ctor是MyGeneric<DateTime>..ctor(DateTime, double)
var declaredType = GetDeclaringType(ctor); //MyGeneric<>
var closedType = declaredType.MakeGenericType(typeof(int));//MyGeneric<int>
//constructors
var typeInfo = closedType.GetTypeInfo();
var constructors = typeInfo.GetConstructors();
//MyGeneric<int>..ctor(int, double)
var constructorWithDouble = constructors
.Where(ctor => ctor.GetParameters().Skip(1).First().ParameterType == typeof(double))
.First();