是否可以根据某些指定的类型在运行时创建一般类型的Action?在这个特定场景中,Action的主体将最终忽略参数类型,因为键入的Action<>将只是一个无争论行动的包装,例如
Action original = () => { };
...
Action<TType> wrapper = (arg) => {
original();
}
或者,甚至:
Action<TTypeA, TTypeB> wrapper = (arg) => {
original();
}
如您所见,键入的Action的主体&lt;&gt;忽略参数及其类型,它只是作为包装器。
如果你好奇我为什么要首先创建这个包装器,那么'基本'版本是我最终将Action转换为Delegate来执行Delegate.Combine(),这需要相同的类型。我试图通过Delegate.Combine()完成的所有操作都是委托被解雇的基本通知。
此时我可能会重新设计我的设计以避免这些类型的恶作剧,但我仍然很好奇如何实现这一目标。
我能得到的最接近的是:
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;
}
答案 0 :(得分:1)
我认为最简单的选择是编写泛型方法然后动态调用它(使用Reflection或甚至可能使用C#4 dynamic
):
class Helper {
public static Action<TType> Wrap1<TType>(Action arg) {
return (arg) => { original(); }
}
}
使用Reflection调用方法并使用typ1
作为泛型类型参数可能如下所示:
var meth = typeof(Helper).GetMethod("Wrap1");
var gmeth = meth.MakeGenericMethod(new[] { typ1 });
var genericAction = gmeth.Invoke(null, new object[] { action });
答案 1 :(得分:1)
如果您不想使用反射,可以设置这样的类。
public class ActionWrapper<TTypeA>
{
protected readonly Action _original;
public ActionWrapper(Action original)
{
_original = original;
}
public Action<TTypeA> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a)
{
_original();
}
}
public class ActionWrapper<TTypeA,TTypeB>:ActionWrapper<TTypeA>
{
public ActionWrapper(Action original) : base(original)
{
}
public new Action<TTypeA, TTypeB> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a,TTypeB b)
{
_original();
}
}