在运行时将委托转换为 Action<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);
// 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
并使用 DynamicInvoke
不是 性能明智的。
我将 Delegate
转换(硬编码)到 Action<T> \ Func<T>
中,我的表现有了巨大的提升。
然后我尝试在运行时将 Delegate
转换为 Action<T> \ Func<T>
(使用 Convert.ChangeType
和 dynamic
),但我的表现受到了伤害——可能是因为我正在使用 dynamic
类型。
我很确定我可以在没有 dynamic
的情况下做到这一点。
我猜测解决方案与expression trees
有关,但我不太确定如何编写这样的代码。如果有人有一个不使用 expression trees
的好解决方案,那么听到它也会很有趣。
您需要使用 Action 或 Func 来动态 get/set 一个 属性 吗?
如果没有,您可以使用 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(...)
如果您的 objective 能够在编译时不知道 return 类型的情况下调用您的 action/function,那么您可能希望以 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%
我正在尝试通过为 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);
CreateDelegate
returns a Delegate
并使用 DynamicInvoke
不是 性能明智的。
我将 Delegate
转换(硬编码)到 Action<T> \ Func<T>
中,我的表现有了巨大的提升。
然后我尝试在运行时将 Delegate
转换为 Action<T> \ Func<T>
(使用 Convert.ChangeType
和 dynamic
),但我的表现受到了伤害——可能是因为我正在使用 dynamic
类型。
我很确定我可以在没有 dynamic
的情况下做到这一点。
我猜测解决方案与expression trees
有关,但我不太确定如何编写这样的代码。如果有人有一个不使用 expression trees
的好解决方案,那么听到它也会很有趣。
您需要使用 Action
如果没有,您可以使用 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(...)
如果您的 objective 能够在编译时不知道 return 类型的情况下调用您的 action/function,那么您可能希望以 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
;