在运行时将委托转换为操作<T>或 Func<T>



我正试图通过为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),我的性能受到伤害-可能是由于我使用dynamic类型。


我很确定没有dynamic我也能做到。

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

如果您的目标是能够在不知道编译时返回类型的情况下调用操作/函数,那么您可能希望最终使用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%左右。

是否需要使用Action或Func来动态获取/设置属性?

如果没有,可以使用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(...)

相关内容

  • 没有找到相关文章

最新更新