创建genericly类型的动作&LT;&GT;在运行时 [英] Creating a genericly typed Action<> at runtime
问题描述
是否有可能在运行时创建基于某些特定类型的一个一般类型化的行动?在这个特殊的情况下,动作的身体会最终忽略的参数类型,类型化的动作&LT;>将只是围绕一个无参数的动作的包装,如:
动作原=()=&GT; {};
...
动作&LT; Af - Ag型&GT;包装=(ARG)=&GT; {
原版的();
}
或者,即使是:
动作&LT; TTypeA,TTypeB&GT;包装=(ARG)=&GT; {
原版的();
}
正如你所看到的,类型化的行动和LT的身体;>忽略的参数,它们的类型,它只是作为一个包装
如果你很好奇,为什么我要创建这个包装摆在首位,基本的版本是,我的行动,最终转换为委托做一个Delegate.Combine(),这需要相同的类型。所有我试图完成与Delegate.Combine()是一个基本的通知,委托被解雇了。
在这一点上我可能会重新工作,我的设计,以避免这些类型的有心计,但是我还是很好奇,这是如何实现。
最近我能得到的是以下内容:
私有静态Af - Ag型GetTypedDelegate&LT; Af - Ag型&GT;(动作的onComplete)
其中,Af - Ag型:类
{
MethodInfo的信息= typeof运算(Af - Ag型).GetMethod(调用);
信息参数[]参数= info.GetParameters();
对象的结果;
如果(parameters.Length == 0)
结果=的onComplete;
否则,如果(parameters.Length == 1)
结果= GetTypedDelegate&LT; Af - Ag型&GT;(的onComplete,参数,[0] .ParameterType);
// 等等
Af - Ag型onCompleteCasted = Delegate.CreateDelegate(typeof运算(Af - Ag型),因此,调用)作为Af - Ag型;
返回onCompleteCasted;
}
私有静态代表GetTypedDelegate&LT; Af - Ag型&GT;(动作的onComplete,型型)
{
//这行是不是对我很有用,现在,因为我不能只创建一个新的
有参数的构造函数的动作//实例...但我想我会扔在这里的情况下,它是使用
输入操作类型= typeof运算(动作&LT;&GT;)。MakeGenericType(新[] {类型});
//这里做一些魔术的类型信息
//当然,以下不工作,但你得到了什么,我瞄准的想法
动作&LT;类型&GT;包装=(ARG1)=&GT;
{
的onComplete();
};
返回包装为代表;
}
我认为,最简单的方法是写一个通用的方法,然后动态地调用它(使用反射或者甚至可能使用C#4 动态
):
类助手{
公共静态动作&LT; Af - Ag型&GT; Wrap1&LT; Af - Ag型&GT;(动作ARG){
回报(ARG)=&GT; { 原版的(); }
}
}
调用方法使用反射,并使用 TYP1
作为泛型类型参数看起来是这样的:
VAR甲基= typeof运算(助手).GetMethod(Wrap1);
VAR gmeth = meth.MakeGenericMethod(新[] {TYP1});
VAR genericAction = gmeth.Invoke(空,新的对象[] {动作});
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();
}
Or, even:
Action<TTypeA, TTypeB> wrapper = (arg) => {
original();
}
As you can see, the body of the typed Action<> ignores the arguments, and their type, it's just acting as a wrapper.
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;
}
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(); }
}
}
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 });
这篇关于创建genericly类型的动作&LT;&GT;在运行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!