如何从MethodInfo的创建委托时,方法签名不能事先知道? [英] How to create a delegate from a MethodInfo when method signature cannot be known beforehand?
问题描述
我需要一个方法,需要一个的MethodInfo
实例重新presenting非泛型静态方法与任意的签名,并返回绑定到该方法可稍后委托使用 Delegate.DynamicInvoke
方法被调用。我的第一天真的尝试是这样的:
I need a method that takes a MethodInfo
instance representing a non-generic static method with arbitrary signature and returns a delegate bound to that method that could later be invoked using Delegate.DynamicInvoke
method. My first naïve try looked like this:
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
重presenting相匹配的签名的委托实例所提供的的MethodInfo
实例?
I hoped that the MethodInfo.CreateDelegate
method could figure out the correct delegate type itself. Well, obviously it cannot. So, how do I create an instance of System.Type
representing a delegate with a signature matching the provided MethodInfo
instance?
推荐答案
您可以使用<一个href="http://msdn.microsoft.com/en-us/library/system.linq.ex$p$pssions.ex$p$pssion.getdelegatetype.aspx">System.Linq.Ex$p$pssions.Ex$p$pssion.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
。
There is probably a copy-paste error in the 2nd check for !method.IsStatic
- you shouldn't use ArgumentNullException
there. And it is a good style to provide a parameter name as an argument to ArgumentException
.
使用 method.IsGenericMethod
如果你想拒绝所有的通用方法和 method.ContainsGenericParameters
如果你要拒绝只有无取代类型参数泛型方法。
Use method.IsGenericMethod
if you want to reject all generic methods and method.ContainsGenericParameters
if you want to reject only generic methods having unsubstituted type parameters.
这篇关于如何从MethodInfo的创建委托时,方法签名不能事先知道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!