我需要采取的方法MethodInfo
表示与任意的签名非泛型静态方法实例,并返回绑定到可以在以后使用调用该方法的委托Delegate.DynamicInvoke
方法。 我第一次尝试天真是这样的:
using System;
using System.Reflection;
class Program
{
static void Main()
{
var method = CreateDelegate(typeof (Console).GetMethod("WriteLine", new[] {typeof (string)}));
method.DynamicInvoke("Hello world");
}
static Delegate CreateDelegate(MethodInfo method)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
if (!method.IsStatic)
{
throw new ArgumentNullException("method", "The provided method is not static.");
}
if (method.ContainsGenericParameters)
{
throw new ArgumentException("The provided method contains unassigned generic type parameters.");
}
return method.CreateDelegate(typeof(Delegate)); // This does not work: System.ArgumentException: Type must derive from Delegate.
}
}
我希望MethodInfo.CreateDelegate
方法可以计算出正确的委托类型本身。 那么,显然不能。 那么,如何创建实例System.Type
表示与匹配所提供的签名的委托MethodInfo
实例?
您可以使用System.Linq.Expressions.Expression.GetDelegateType方法:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
class Program
{
static void Main()
{
var writeLine = CreateDelegate(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }));
writeLine.DynamicInvoke("Hello world");
var readLine = CreateDelegate(typeof(Console).GetMethod("ReadLine", Type.EmptyTypes));
writeLine.DynamicInvoke(readLine.DynamicInvoke());
}
static Delegate CreateDelegate(MethodInfo method)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
if (!method.IsStatic)
{
throw new ArgumentException("The provided method must be static.", "method");
}
if (method.IsGenericMethod)
{
throw new ArgumentException("The provided method must not be generic.", "method");
}
return method.CreateDelegate(Expression.GetDelegateType(
(from parameter in method.GetParameters() select parameter.ParameterType)
.Concat(new[] { method.ReturnType })
.ToArray()));
}
}
有可能是在第二检查拷贝-粘贴错误!method.IsStatic
-你不应该使用ArgumentNullException
那里。 它是一个良好的作风,以提供一个参数名作为参数传递给ArgumentException
。
使用method.IsGenericMethod
如果你想拒绝所有通用的方法和method.ContainsGenericParameters
如果您想拒绝无取代类型参数仅泛型方法。
你可能想尝试System.LinQ.Expressions
...
using System.Linq.Expressions;
...
static Delegate CreateMethod(MethodInfo method)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
if (!method.IsStatic)
{
throw new ArgumentException("The provided method must be static.", "method");
}
if (method.IsGenericMethod)
{
throw new ArgumentException("The provided method must not be generic.", "method");
}
var parameters = method.GetParameters()
.Select(p => Expression.Parameter(p.ParameterType, p.Name))
.ToArray();
var call = Expression.Call(null, method, parameters);
return Expression.Lambda(call, parameters).Compile();
}
并且以后将其用作以下
var method = CreateMethod(typeof (Console).GetMethod("WriteLine", new[] {typeof (string)}));
method.DynamicInvoke("Test Test");
文章来源: How to create a delegate from a MethodInfo when method signature cannot be known beforehand?