创建通用类型的Action& lt;& gt;在运行时 [英] Creating a genericly typed Action<> at runtime

查看:44
本文介绍了创建通用类型的Action& lt;& gt;在运行时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在运行时基于某些指定类型创建通用类型的Action?在这种特定情况下,Action的主体最终将忽略参数类型,因为类型化的Action<>只是无参Action(例如

Is it possible to create a generically typed Action at run time based on some specified types? In this particular scenario, the body of the Action will ultimately ignore the argument types, as the typed Action<> will just be a wrapper around a no-argument Action, e.g.

Action original = () => { };
...
Action<TType> wrapper = (arg) => {
    original();
}

或者,甚至:

Action<TTypeA, TTypeB> wrapper = (arg) => {
    original();
}

如您所见,类型化的Action<>的主体会忽略参数及其类型,而只是充当包装器.

As you can see, the body of the typed Action<> ignores the arguments, and their type, it's just acting as a wrapper.

如果您对为什么要首先创建此包装器感到好奇,那么基本"版本是我最终将Action转换为Delegate以执行Delegate.Combine(),它需要相同的类型.我要使用Delegate.Combine()来完成的工作只是基本通知,该代表被解雇了.

If you're curious as to why I want create this wrapper in the first place, the 'basic' version is that I am ultimately converting the Action to a Delegate for doing a Delegate.Combine(), which requires identical types. All I am trying to accomplish with the Delegate.Combine() is a basic notification that the delegate was fired.

在这一点上,我可能会重新设计以避免这些类型的恶作剧,但我仍然非常好奇如何实现这一目标.

At this point I will probably re-work my design to avoid these types of shenanigans, but I am still very curious how this might be accomplished.

我能找到的最接近的是:

The closest I could get was the following:

private static TType GetTypedDelegate<TType>(Action onComplete)
        where TType : class
    {
        MethodInfo info = typeof(TType).GetMethod("Invoke");
        ParameterInfo[] parameters = info.GetParameters();

        object result;
        if (parameters.Length == 0)
            result = onComplete;
        else if (parameters.Length == 1)
            result = GetTypedDelegate<TType>(onComplete, parameters[0].ParameterType);
        // etc

        TType onCompleteCasted = Delegate.CreateDelegate(typeof(TType), result, "Invoke") as TType;
        return onCompleteCasted;
    }

    private static Delegate GetTypedDelegate<TType>(Action onComplete, Type type)
    {
        // This line isn't useful for me right now, since I can't just create a new
        // instance of the action with a parameterless constructor ... but I thought I'd throw it in here in case it was of use
        Type actionType = typeof(Action<>).MakeGenericType(new[] { type });

        // Do some magic here with the type information
        // The following of course does not work,but you get the idea of what I am aiming for

        Action<type> wrapper = (arg1) =>
        {
            onComplete();
        };

        return wrapper as Delegate;
    }

推荐答案

我认为最简单的选择是编写一个通用方法,然后动态调用它(使用Reflection或什至使用C#4 dynamic):

I think that the easiest option is to write a generic method and then invoke it dynamically (using Reflection or possibly even using C# 4 dynamic):

class Helper {
  public static Action<TType> Wrap1<TType>(Action arg) {
    return (arg) => { original(); }
  }
}

使用Reflection调用方法,并使用typ1作为通用类型参数,如下所示:

Invoking the method using Reflection and using typ1 as the generic type argument could look like this:

var meth = typeof(Helper).GetMethod("Wrap1");
var gmeth = meth.MakeGenericMethod(new[] { typ1 });
var genericAction = gmeth.Invoke(null, new object[] { action });

这篇关于创建通用类型的Action&amp; lt;&amp; gt;在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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