将委托转换为动作T。或Func< T>在运行时 [英] Casting a Delegate into an Action<T> or Func<T> in runtime
问题描述
我试图通过为 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);
//我想更改此部分,而不要使用动态内容!
dynamic castedGet = Convert.ChangeType(getMethod,getType);
动态castedSet = Convert.ChangeType(setMethod,setType);
CreateDelegate
返回委派
并使用 DynamicInvoke
不是明智的效果。
我将 Delegate
投射(硬编码)到 Action< T> \ Func< T>
并看到我的表现大大提高。
然后我尝试投放 Delegate
放入 Action< T> runtime Func< T>
在运行时(使用 Convert.ChangeType
和 dynamic
)和我的表现受到了伤害-可能是由于我使用的是 dynamic
类型。
我非常确定我可以在没有 dynamic
的情况下执行此操作。
我猜测解决方案与表达式树
有关,但是我不确定如何编写类似这样的代码。如果某人有一个很好的解决方案,但不使用表达式树
,那么也很有趣。
如果您的目标是能够在编译时不知道返回类型的情况下调用操作/函数,那么您可能希望以结尾Action< object>
和 Func< object>
,对吧?
无需编译表达式树或其他任何东西,就像这样:
//使用反射来创建动作,调用方法下面。
var setAction =(Action< object>)this.GetType()
.GetMethod( CastAction,BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(prop.PropertyType)
.Invoke(null,new object [] {setMethod});
//调用如下操作:
object value = 42; //或任何正确类型的值。
setAction(value);
使用此辅助方法:
private static Action< object> CastAction< T>(代表d)
{
var action =(Action< T>)d;
return obj =>动作((T)obj);
}
我的测试表明,这比使用<$ c $快25% c>动态,比只说 obj.Prop = 2
;
慢约45%
I'm trying to improve my reflection code by creating Delegates for the Getter
and Setter
methods.
My code looks like this:
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
returns a Delegate
and using DynamicInvoke
isn't performance wise.
I casted (hardcoded) the Delegate
into Action<T> \ Func<T>
and saw a huge increase in my performance.
I then tried to cast the Delegate
into Action<T> \ Func<T>
in runtime (using Convert.ChangeType
and dynamic
) and my performance got hurt - probably due to the fact that I'm using a dynamic
type.
I'm pretty sure that I can do this without dynamic
.
I guess the solution has something to do with expression trees
, but I'm not really sure how to code something like this. If someone has a good solution that doesn't use expression trees
than it will be interesting to hear about it as well.
If your objective is to be able to invoke your action/function without knowing the return type at compile time, then you probably want to end up with an Action<object>
and Func<object>
, right?
You can do this without having to compile an expression tree or anything, like so:
// 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);
Using this helper method:
private static Action<object> CastAction<T>(Delegate d)
{
var action = (Action<T>)d;
return obj => action((T)obj);
}
My tests show this to be roughly 25% faster than using dynamic
, and about 45% slower than just saying obj.Prop = 2
;
这篇关于将委托转换为动作T。或Func< T>在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!