如何从打开的泛型类型为属性getter创建委托

时间:2018-01-24 12:45:36

标签: c# generics reflection

我有一个开放泛型类型属性的PropertyInfo,通过以下方式获得:

public interface ITest<T>
{
    T Item { get; }
}

var propertyInfo = typeof(ITest<>).GetProperty("Item");

我希望能够创建一个具体的,可调用的委托,从Func<ITest<int>, int>填写类类型参数(例如propertyInfo)。

显而易见的是propertyInfo.GetMethod.MakeGenericMethod(typeof(int)).CreateDelegate(...),但由于GetMethod不是通用的,因此失败,因为它是通用类的属性。

我知道您可以通过将类型参数应用于之前的类型(例如typeof(ITest<int>).GetProperty("Item").GetMethod.CreateDelegate(...))来获取此属性的委托,但我希望只需要在ITest中查找该属性一旦,因为它将为每个类型参数重复相同的搜索。

有没有办法创建此委托,或者只能通过使用typeof(ITest<int>)来开始?

短版

以下TestMethod可以通过CreateGetter的某些实现(假设T::Equals明智地实施)来通过吗?

public void TestMethod<T>(ITest<T> x)
{
    var propertyInfo = typeof(ITest<>).GetProperty("Item");
    var getter = CreateGetter<int>(propertyInfo);

    Assert(getter(x).Equals(x.Item));
}

2 个答案:

答案 0 :(得分:0)

如果您确实想使用PropertyInfo,此方法将起作用:

public static Func<Test<T>, T> CreateGetter<T>(PropertyInfo info)
{
    Type type = info.ReflectedType;

    PropertyInfo genericProperty = type.MakeGenericType(typeof(T)).GetProperty(info.Name);

    return (source) => (T)genericProperty.GetValue(source);
}

否则我会建议:

public static Func<Test<T>, T> GetGenericPropertyDelegate<T>(string propertyName)
{
    PropertyInfo genericProperty = typeof(Test<>).MakeGenericType(typeof(T)).GetProperty(propertyName);

    return (source) => (T)genericProperty.GetValue(source);
}

用法:

public void Test<T>(ITest<T> x)
{
    var getter = GetGenericPropertyDelegate<int>("Item");

    Assert(getter(x).Equals(x.Item));
}

答案 1 :(得分:0)

您需要先实例化泛型类型,然后才能以通常的方式从MethodInfo创建委托。

var target = typeof(ITest<>).MakeGenericType(typeof(int));
var prop = target.GetProperty("Item");
var dlg = prop.GetMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(target, prop.PropertyType));