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

Ami*_*ich 9 c# reflection casting

我正在尝试通过为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);
Run Code Online (Sandbox Code Playgroud)

CreateDelegate返回a Delegate并且使用DynamicInvoke 不是性能明智的.

Delegate投入(硬编码)进入Action<T> \ Func<T>并看到我的表现大幅增加.

然后我试着投了DelegateAction<T> \ Func<T>在运行时(使用Convert.ChangeTypedynamic)和我的表现受到伤害-这可能是由于这样的事实,我使用一个dynamic类型.

我很确定我可以不用这样做dynamic.

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

Str*_*ior 3

如果您的目标是能够在编译时不知道返回类型的情况下调用操作/函数,那么您可能希望以 and 结束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);
Run Code Online (Sandbox Code Playgroud)

使用这个辅助方法:

private static Action<object> CastAction<T>(Delegate d)
{
    var action = (Action<T>)d;
    return obj => action((T)obj);
}
Run Code Online (Sandbox Code Playgroud)

我的测试表明这比使用 大约快 25% dynamic,比直接说 慢大约 45% obj.Prop = 2