How to create a delegate from a MethodInfo when method signature cannot be known beforehand?(当事先无法知道方法签名时,如何从 MethodInfo 创建委托?)
问题描述
我需要一个方法,它接受一个 MethodInfo 实例,该实例表示具有任意签名的非泛型静态方法,并返回一个绑定到该方法的委托,以后可以使用 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 的实例来表示具有与提供的 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?
推荐答案
你可以使用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 是一种很好的风格.
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 创建委托?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:当事先无法知道方法签名时,如何从 MethodInfo 创建委托?
基础教程推荐
- 首先创建代码,多对多,关联表中的附加字段 2022-01-01
- 在 VS2010 中的 Post Build 事件中将 bin 文件复制到物 2022-01-01
- 如何动态获取文本框中datagridview列的总和 2022-01-01
- 是否可以在 asp classic 和 asp.net 之间共享会话状态 2022-01-01
- 错误“此流不支持搜索操作"在 C# 中 2022-01-01
- JSON.NET 中基于属性的类型解析 2022-01-01
- 全局 ASAX - 获取服务器名称 2022-01-01
- 从 VS 2017 .NET Core 项目的发布目录中排除文件 2022-01-01
- 将事件 TextChanged 分配给表单中的所有文本框 2022-01-01
- 经典 Asp 中的 ResolveUrl/Url.Content 等效项 2022-01-01
