在运行时将委托转换为Action <t>或Func <t>

时间:2015-09-21 14:51:12

标签: c# reflection casting

我正在尝试通过为GetterSetter方法创建代理来改进我的反射代码。

我的代码如下所示:

MyObject obj = new MyObject();
var prop = obj.GetType().GetProperty("Prop");
var getType = typeof(Func<>).MakeGenericType(prop.PropertyType);
var setType = typeof(Action<>).MakeGenericType(prop.PropertyType);

var getMethod = prop.GetGetMethod().CreateDelegate(getType, obj);
var setMethod = prop.GetSetMethod().CreateDelegate(setType, obj);

// I'd like to change this section and not to use a dynamic!!
dynamic castedGet = Convert.ChangeType(getMethod, getType);
dynamic castedSet = Convert.ChangeType(setMethod, setType);

CreateDelegate返回Delegate,使用DynamicInvoke 并非表现明智。

我将Delegate投放({硬编码]到Action<T> \ Func<T>并且看到我的表现大幅增加。

然后我尝试在运行时将Delegate转换为Action<T> \ Func<T>(使用Convert.ChangeTypedynamic)并且我的表现受到了伤害 - 可能是因为我' m使用dynamic类型。

我很确定我可以在没有dynamic的情况下执行此操作。

猜测解决方案与expression trees有关,但我不确定如何编写这样的代码。如果某人有一个不使用expression trees的好解决方案,那么听到它也会很有趣。

2 个答案:

答案 0 :(得分:3)

如果您的目标是能够在编译时不知道返回类型的情况下调用您的操作/函数,那么您可能希望最终得到Action<object>Func<object>,对吗?

您可以在不必编译表达式树或任何内容的情况下执行此操作,如下所示:

// Use reflection to create the action, invoking the method below.
var setAction = (Action<object>) this.GetType()
    .GetMethod("CastAction", BindingFlags.Static | BindingFlags.NonPublic)
    .MakeGenericMethod(prop.PropertyType)
    .Invoke(null, new object[]{setMethod});

// invoke the action like this:
object value = 42; // or any value of the right type.
setAction(value);

使用此辅助方法:

private static Action<object> CastAction<T>(Delegate d)
{
    var action = (Action<T>)d;
    return obj => action((T)obj);
}

我的测试表明,这比使用dynamic大约快25%,比仅仅obj.Prop = 2慢了约45%;

答案 1 :(得分:1)

是否有理由需要使用Action&lt; T&gt;或者Func&lt; T&gt;动态获取/设置一个属性?

如果没有,您可以使用PropertyInfo.GetMethod()和SetMethod()

 MyObject obj = new MyObject();
 PropertyInfo prop = obj.GetType().GetProperty("Prop");

 MethodInfo getter = prop.GetMethod();
 getter.Invoke(...)

 MethodInfo setter = prop.SetMethod();
 setter.Invoke(...)