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);
}