cha*_*rit 32 .net reflection delegates methodinfo
谷歌搜索和登陆后,阅读了另一个问题
如果您在编译时不知道参数的数量或类型,是否可以从MethodInfo构建正确的委托?
更多关于此:如果不使用Reflection.Emit或类型构建器,这可以优雅地完成吗?
这对我来说有点令人失望,因为Delegate.CreateDelegate要求我指定正确的Delegate类型作为第一个参数,否则它会抛出异常或调用不正确的方法.
我正在建造一些忍者齿轮,这会有很大的帮助......谢谢!
这是一个通用的解决方案:
/// <summary>
/// Builds a Delegate instance from the supplied MethodInfo object and a target to invoke against.
/// </summary>
public static Delegate ToDelegate(MethodInfo mi, object target)
{
if (mi == null) throw new ArgumentNullException("mi");
Type delegateType;
var typeArgs = mi.GetParameters()
.Select(p => p.ParameterType)
.ToList();
// builds a delegate type
if (mi.ReturnType == typeof(void)) {
delegateType = Expression.GetActionType(typeArgs.ToArray());
} else {
typeArgs.Add(mi.ReturnType);
delegateType = Expression.GetFuncType(typeArgs.ToArray());
}
// creates a binded delegate if target is supplied
var result = (target == null)
? Delegate.CreateDelegate(delegateType, mi)
: Delegate.CreateDelegate(delegateType, target, mi);
return result;
}
Run Code Online (Sandbox Code Playgroud)
注意:我正在构建一个Silverlight应用程序,它将取代之前的javascript应用程序,其中我有多个调用相同Silverlight [ScriptableMember]方法的Javascript接口.
需要支持所有这些遗留的JS接口以及用于访问新功能的新接口,因此自动设置JS接口并将调用"委托"到正确的Silverlight方法将有助于加快工作量.
我不能在这里发布代码,所以这是摘要.
Mar*_*ell 22
说实话,如果你在编译时不知道类型,那么创建一个没有很大的好处Delegate.你不想用DynamicInvoke; 它会和反射一样慢.对此的主要例外是在阴影中潜伏着委托类型,例如订阅事件时 - 在这种情况下EventInfo使其可用.
有关信息,在.NET 3.5中Expression,有:
Expression.GetActionType(params Type[] typeArgs);
Expression.GetFuncType(params Type[] typeArgs)
Run Code Online (Sandbox Code Playgroud)
这可能在某种程度上有所帮助:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
static class Program {
static void Main() {
DoStuff("Test1");
DoStuff("Test2");
}
static void DoStuff(string methodName) {
MethodInfo method = typeof(Program).GetMethod(methodName);
List<Type> args = new List<Type>(
method.GetParameters().Select(p => p.ParameterType));
Type delegateType;
if (method.ReturnType == typeof(void)) {
delegateType = Expression.GetActionType(args.ToArray());
} else {
args.Add(method.ReturnType);
delegateType = Expression.GetFuncType(args.ToArray());
}
Delegate d = Delegate.CreateDelegate(delegateType, null, method);
Console.WriteLine(d);
}
public static void Test1(int i, DateTime when) { }
public static float Test2(string x) { return 0; }
}
Run Code Online (Sandbox Code Playgroud)
如果您事先不知道参数的数量或类型,可能这意味着您不知道要创建的委托类型?
如果是这样的话,你就会陷入绝对一般的情况.
但是,对于大多数常见情况(没有参考/输出参数,使用现有类型之一的参数很少),您可以使用其中一个Func或多个Action代表.(.NET 4.0有大量参数的Func/ Action类型,所以实际上你只需要担心out/ref参数.)如果方法有一个非void返回类型使用Func,否则使用Action.根据参数的数量确定要使用的类型,例如
static readonly Type[] FuncTypes = { typeof(Func),
typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), /* etc */ };
Run Code Online (Sandbox Code Playgroud)
使用Type.MakeGenericType参数类型和返回类型来获取正确的委托类型,然后Delegate.CreateDelegate应该工作.
我现在没有时间处理样品,但如果您以后要我,请告诉我.
一个问题:你打算如何使用这个代表?其他东西需要知道如何执行它,当然......
为什么那么复杂?
public static Delegate CreateDelegate(this MethodInfo method)
{
return Delegate.CreateDelegate
(
Expression.GetDelegateType
(
method.GetParameters()
.Select(p => p.ParameterType)
.Concat(new Type[] { method.ReturnType })
.ToArray()
),
null,
method
);
}
Run Code Online (Sandbox Code Playgroud)
[旁注:我给这个方法加了前缀"创建......"."为......"令人困惑,因为它误导你认为这是转换.]