我希望能够在运行时做等同于以下内容:
var action = new Action<ANYTHING AT RUNTIME>(obj => Console.WriteLine("Called = " + obj));
我知道我需要的正确类型的行动,但不知道如何使用Delegate.Create得到最终的位。 Type
代表在行动定义吨。
var actionType = typeof(Action<>).MakeGenericType(Type);
var constructor = actionType.GetConstructors()[0];
var @delegate = Delegate.CreateDelegate(actionType, <WHAT GOES HERE>);
点人们似乎缺少的是我想创造一个T不能静态,因为它正在从属性派生的类使用指定的操作实例 - 此装置T可以是任何东西,它不能被定义为一般定义
干杯
如果你知道你需要执行的,以及如何不论类型执行它(在你的例子)的操作,为什么不只是使执行操作的通用方法,并创建您的代理呀?
class Program
{
public static void Perform<T>(T value)
{
Console.WriteLine("Called = " + value);
}
public static Delegate CreateAction(Type type)
{
var methodInfo = typeof (Program).GetMethod("Perform").MakeGenericMethod(type);
var actionT = typeof (Action<>).MakeGenericType(type);
return Delegate.CreateDelegate(actionT, methodInfo);
}
static void Main(string[] args)
{
CreateAction(typeof (int)).DynamicInvoke(5);
Console.ReadLine();
}
}
您可以使用下面的代码,它的工作原理,如果类型可以铸造一个对象:
Action<object> func = o => Console.WriteLine("Called = " + o.GetType().Name);
var actionType = typeof(Action<>).MakeGenericType(type);
var constructor = actionType.GetConstructors()[0];
var @delegate = Delegate.CreateDelegate(actionType, func.Method);
然而,如果类型是枚举,否则将无法正常工作等价值型。
感谢“@prashanth”建议,我管理动态创建和调用一个动作<>与运行时类型得益于动态关键字:
public Action<dynamic> GetDynamicAction(/* some params */)
{
return oDyn =>
{
//here is the action code with the use of /* some params */
};
}
例如,用基本动作的处理程序:
public class ActionHandler
{
public ReturnType DoAction<T>(Action<T> t)
{
//whatever needed
}
}
使用案例:
/* some params */ = Any runtime type specific data (in my case I had a Type and a MethodInfo passed as parameters and that were called in the action)
var genericMethod = actionHandler.GetType().GetMethod(nameof(ActionHandler.DoAction));
var method = genericMethod.MakeGenericMethod(runtimeGenericType);
var actionResult = (ReturnType) method.Invoke(actionHandler, new object[]
{
GetDynamicAction(/*some params*/)
}
);
简短的答案是创建一个委托MyActionDelegate
,然后使用:
delegate void MyActionDelegate(T arg);
Delegate @delegate = new MyActionDelegate((a) => Console.WriteLine(a));
下面是一个使用泛型类的工作示例:
public class MyClass<T>
{
public delegate void ActionDelegate(T arg);
public void RunGenericAction(T arg)
{
var actionType = typeof(Action<>).MakeGenericType(typeof(T));
var constructor = actionType.GetConstructors()[0];
Delegate @delegate = new ActionDelegate((a) => { Console.WriteLine(arg); });
var inst = (Action<T>)constructor.Invoke(new object[] {
@delegate.Target,
@delegate.Method.MethodHandle.GetFunctionPointer()
});
inst(arg);
}
}
这样使用它,它输出123
到控制台:
var c = new MyClass<int>();
c.RunGenericAction(123);
你会注意到我传递两个参数Constructor.Invoke
; 这是因为事实证明,委托说法实际上编译为两个参数:该函数的目标对象和函数指针。 我不能把信贷的花式步法有; “借用”从信息如何通过使用反射委托论证这个优秀的答案。
使用下面的代码来创建一个委托,这是在型号参数后期绑定。 另请参阅如何:检查和实例化泛型类型与反思 。
abstract class ActionHelper {
protected abstract Delegate CreateActionImpl();
// A subclass with a static type parameter
private class ActionHelper<T> : ActionHelper {
protected override Delegate CreateActionImpl() {
// create an Action<T> and downcast
return new Action<T>(obj => Console.WriteLine("Called = " + (object)obj));
}
}
public static Delegate CreateAction(Type type) {
// create the type-specific type of the helper
var helperType = typeof(ActionHelper<>).MakeGenericType(type);
// create an instance of the helper
// and upcast to base class
var helper = (ActionHelper)Activator.CreateInstance(helperType);
// call base method
return helper.CreateActionImpl();
}
}
// Usage
// Note: The "var" is always "Delegate"
var @delegate = ActionHelper.CreateAction(anyTypeAtRuntime);
这就是说,我不建议使用这种方法。 相反,使用
Action<object> action = obj => Console.WriteLine("Called = " + obj);
它提供