创建具有更改的返回类型的getter委托

时间:2018-06-25 17:26:54

标签: c# .net

我需要将所有属性映射到Func。我该怎么办?

我上课

class A 
{
    public int SomeIntValue { get; }
    public string SomeStringValue { get; }
    public Dictionary<...> SomeDictionary { get; }
}

和字典Dictionary<string, Func<A, object>>。 我正在尝试为getter方法创建委托,但我真的不知道该怎么做。

以这种方式,它是行不通的,并且为什么会这样。我需要间接地做,但是怎么做?

(Func<TType, object>) Delegate.CreateDelegate(typeof(Func<TType, object>), null, property.GetGetMethod())

2 个答案:

答案 0 :(得分:2)

您遇到的问题是从Func<A, int>Func<A, object>的转换不是保留表示的转换,因此不允许通过Func系列的声明中提供的方差修饰符来进行转换。代表。对于值类型,您需要添加一条额外的IL指令,这是装箱转换。下面我提供了一种解决方案,该解决方案生成一种动态方法以在必要时(即当返回值是值类型时)添加所需的指令。它也更有效,因为它直接调用该属性,而不是依靠反射来处理调用。

using System.Reflection.Emit;

public static Dictionary<string, Func<T, object>> GetGetMethods<T>()
{
    var getMethods = new Dictionary<string, Func<T, object>>();
    foreach (var prop in typeof(T).GetProperties())
    {    
        Func<T, object> del;
        if (prop.PropertyType.IsValueType)
        {
            var dynMethod = new DynamicMethod(string.Format("Dynamic_Get_{0}_{1}", typeof(T).Name, prop.Name), typeof(object), new[] { typeof(T) }, typeof(T).Module);
            var ilGen = dynMethod.GetILGenerator();
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Callvirt, prop.GetGetMethod());
            ilGen.Emit(OpCodes.Box, prop.PropertyType);
            ilGen.Emit(OpCodes.Ret);

            del = (Func<T, object>)dynMethod.CreateDelegate(typeof(Func<T, object>));
        }
        else
        {
            del = (Func<T, object>)Delegate.CreateDelegate(typeof(Func<T, object>), null, prop.GetGetMethod());
        }

        getMethods[prop.Name] = del;
    }

    return getMethods;
}

答案 1 :(得分:1)

我想您可以使用方法组runApp创建委托:

somePropertyInfo.GetValue

然后您可以将其放入字典中。

您不需要Func<A, object> del = somePropertyInfo.GetValue; 调用,因为GetGetMethod将调用getter。该方法用于将属性作为GetValue对象。在这里,您不需要MethodInfo