将委托转换为动作T。或Func< T>在运行时 [英] Casting a Delegate into an Action<T> or Func<T> in runtime

查看:56
本文介绍了将委托转换为动作T。或Func< T>在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过为 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&lt; T&gt;在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆