C# 将一名代表付诸行动<;T>;或Func<;T>;运行时

C# 将一名代表付诸行动<;T>;或Func<;T>;运行时,c#,reflection,casting,C#,Reflection,Casting,我试图通过为Getter和Setter方法创建委托来改进我的反射代码 我的代码如下所示: MyObject obj = new MyObject(); var prop = obj.GetType().GetProperty("Prop"); var getType = typeof(Func<>).MakeGenericType(prop.PropertyType); var setType = typeof(Action<>).MakeGenericType(prop

我试图通过为
Getter
Setter
方法创建委托来改进我的反射代码

我的代码如下所示:

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);
MyObject obj=新的MyObject();
var prop=obj.GetType().GetProperty(“prop”);
var getType=typeof(Func).MakeGenericType(prop.PropertyType);
var setType=typeof(Action).MakeGenericType(prop.PropertyType);
var getMethod=prop.getMethod().CreateDelegate(getType,obj);
var setMethod=prop.GetSetMethod().CreateDelegate(setType,obj);
//我想更改此部分,而不是使用动态!!
动态castedGet=Convert.ChangeType(getMethod,getType);
动态castedSet=Convert.ChangeType(setMethod,setType);
CreateDelegate
返回一个
Delegate
,使用
DynamicInvoke
不符合性能要求

我将
委托
硬编码为
Action\Func
,并看到我的表现有了巨大的提高

然后,我尝试在运行时(使用
Convert.ChangeType
dynamic
)将
委托
转换为
Action\Func
),我的性能受到了影响-可能是因为我使用了
dynamic
类型

我很确定我可以在没有
动态
的情况下完成这项工作


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

您需要使用Action或Func来动态获取/设置属性吗

如果没有,则可以使用和SetMethod()


如果您的目标是能够在编译时在不知道返回类型的情况下调用操作/函数,那么您可能希望以
操作
函数
结束,对吗

您无需编译表达式树或任何东西即可执行此操作,如:

// 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);
//使用反射创建操作,调用下面的方法。
var setAction=(Action)this.GetType()
.GetMethod(“CastAction”,BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(prop.PropertyType)
.Invoke(null,新对象[]{setMethod});
//像这样调用操作:
对象值=42;//或任何正确类型的值。
设定动作(值);
使用此帮助器方法:

private static Action<object> CastAction<T>(Delegate d)
{
    var action = (Action<T>)d;
    return obj => action((T)obj);
}
私有静态动作强制执行(委托d)
{
var action=(action)d;
返回obj=>action((T)obj);
}

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

您是每次都执行所有这些代码,还是将代理缓存在某个地方然后调用它们?@Dai-这是我代码的一小部分,也是一个示例。我正在寻找为每个属性缓存propertyinfo、getter和setter的方法——以一种懒惰的方式。你为什么要使用
dynamic
Convert.ChangeType
不返回后期绑定对象。@Dai-我正在使用动态,因为我想以某种方式调用这些方法。下面是表达式树的答案-原因是性能。使用MethodInfo.Invoke比创建委托并调用它们慢得多(假设我想缓存它们)。无论如何,谢谢。我不知道(也从来没有想过,也从来没有检查过自己)使用
Invoke()
比使用
dynamic
键入要慢,@k3b-answer之间有什么区别?OP说“使用MethodInfo.Invoke比创建委托并调用委托慢得多”@codroipo:在这种情况下,我使用
MethodInfo.Invoke()
只是首先创建委托。这是OP的
ChangeType
方法在幕后有效地完成的事情。然而,结果
setAction
操作的调用速度远远快于调用
setter.Invoke()
,k3b的答案就是如此。它比调用动态
castedSet
操作要快一些,因为它不依赖于动态调用。@StriplingWarrior-这非常有趣。基准测试比使用动态转换更好,比使用硬编码转换更慢。目前这是我拥有的最快的通用方法。谢谢你的回答。我在等待更多的答案,如果没有更好的答案,我会接受的。谢谢+1.@StriplingWarrior好的,今天早上,头脑清醒,我明白你在做什么。绝对+1
private static Action<object> CastAction<T>(Delegate d)
{
    var action = (Action<T>)d;
    return obj => action((T)obj);
}