我想引用的方法定义如下:
class Foo<T1> {
void Bar<T2>(int value) {...}
}
我的问题与具有通用参数的Foo和Bar相关联 如果我使用
static public GenericInstanceMethod MakeGenericMethod(this MethodReference method, TypeReference[] genericArguments)
{
var _method = new GenericInstanceMethod(method);
foreach (var _argument in genericArguments) {
_method.GenericArguments.Add(genericArguments);
}
return _method;
}
生成的代码将引用
Foo<>.Bar<T2>(int)
如果我使用
static public MethodReference Reference(this GenericInstanceType genericInstanceType, MethodReference method)
_methodReference = new MethodReference(method.Name, _returnType, genericInstanceType) {
HasThis = method.HasThis,
ExplicitThis = method.ExplicitThis,
CallingConvention = method.CallingConvention
};
foreach (var parameter in method.Parameters) {
_methodReference.Parameters.Add(parameter);
}
return _methodReference;
}
生成的代码将引用
Foo<T1>.Bar(int);
两者都是我的期望,但不是我想要的,我找不到将它们组合起来产生正确值的方法
答案 0 :(得分:0)
您需要从方法引用中创建一个通用实例方法:
using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using TypeAttributes = Mono.Cecil.TypeAttributes;
namespace TestGenericMethod
{
public class Foo<T>
{
public void M<X>(X x)
{
Console.WriteLine(x);
}
}
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
var p = new Program();
p.Test(args[0]);
return;
}
var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var tr = a.MainModule.ImportReference(typeof(Foo<int>));
var tm = a.MainModule.Types.SingleOrDefault(t => t.Name == "Program").Methods.SingleOrDefault(m => m.Name == "Test");
var gm = new MethodReference("M", a.MainModule.TypeSystem.Void, tr);
var genericParameter = new GenericParameter("X", gm);
gm.GenericParameters.Add(genericParameter);
gm.Parameters.Add(new ParameterDefinition(genericParameter));
gm.HasThis = true;
var mmm = new GenericInstanceMethod(gm);
mmm.GenericArguments.Add(a.MainModule.TypeSystem.String);
Console.WriteLine(gm.GetType().FullName);
var il = tm.Body.GetILProcessor();
var ret = il.Body.Instructions.SingleOrDefault(i => i.OpCode == OpCodes.Ret);
il.InsertBefore(ret, il.Create(OpCodes.Ldloc_0));
il.InsertBefore(ret, il.Create(OpCodes.Ldarg_1));
il.InsertBefore(ret, il.Create(OpCodes.Callvirt, mmm));
a.Write("Output.exe");
}
private void Test(string s)
{
var o = new Foo<int>();
}
}
}