我正在尝试发出一个方法,该方法在newobj instance void class [mscorlib]System.Lazy`1<class Example.ExpensiveType>::.ctor(class [mscorlib]System.Func`1<class Example.ExpensiveType>)
行
使用ILDasm查看其他地方,我发现正确的调用看起来像这样:
newobj instance void class [mscorlib]System.Lazy`1<class Example.IHeater>::.ctor(class [mscorlib]System.Func`1<!0>)
不幸的是,我不知道如何使用Mono.Cecil API重现这一点。有人可以帮助使用仿制药吗?
这是我到目前为止所拥有的:
var get = new MethodDefinition(
"Get",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
ModuleDefinition.TypeSystem.Object);
var funcType = new GenericInstanceType(ImportedTypes.FuncOfT);
funcType.GenericArguments.Add(lazyElementType);
var funcTypeCtor = new MethodReference(".ctor", ModuleDefinition.TypeSystem.Void, funcType);
funcTypeCtor.Parameters.Add(new ParameterDefinition(ModuleDefinition.TypeSystem.Object));
funcTypeCtor.Parameters.Add(new ParameterDefinition(ModuleDefinition.TypeSystem.IntPtr));
funcTypeCtor.HasThis = true;
funcTypeCtor = ModuleDefinition.Import(funcTypeCtor);
var lazyTypeCtor = new MethodReference(".ctor", ModuleDefinition.TypeSystem.Void, lazyType);
var parameterDefinition = new ParameterDefinition(funcType);
lazyTypeCtor.Parameters.Add(parameterDefinition);
lazyTypeCtor.HasThis = true;
lazyTypeCtor = ModuleDefinition.Import(lazyTypeCtor);
il = get.Body.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldftn, getTypedValue);
il.Emit(OpCodes.Newobj, funcTypeCtor);
il.Emit(OpCodes.Newobj, lazyTypeCtor); // This leads to the invalid token
il.Emit(OpCodes.Ret);
lazyBinding.Methods.Add(get);
任何帮助都会非常感激 - 我很难过!
答案 0 :(得分:9)
我发现这个答案埋藏在一个已有数年历史的邮件列表档案中(感谢GáborKozár!)。我没有正确创建/导入泛型类型及其方法。正确加载Lazy<T>
和Func<T>
类型的代码如下:
var genericArgument = lazyElementType;
var funcType = ModuleDefinition.Import(typeof(Func<>)).MakeGenericInstanceType(genericArgument);
var funcCtor =
ModuleDefinition.Import(funcType.Resolve()
.Methods.First(m => m.IsConstructor && m.Parameters.Count == 2))
.MakeHostInstanceGeneric(genericArgument);
var lazyType = ModuleDefinition.Import(typeof(Lazy<>)).MakeGenericInstanceType(genericArgument);
var lazyCtor =
ModuleDefinition.Import(lazyType.Resolve()
.GetConstructors()
.First(m => m.Parameters.Count == 1
&& m.Parameters[0].ParameterType.Name.StartsWith("Func")))
.MakeHostInstanceGeneric(genericArgument);
// Method body as above
上面的关键是扩展方法MakeHostInstanceGeneric
,定义为
public static MethodReference MakeHostInstanceGeneric(
this MethodReference self,
params TypeReference[] args)
{
var reference = new MethodReference(
self.Name,
self.ReturnType,
self.DeclaringType.MakeGenericInstanceType(args))
{
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis,
CallingConvention = self.CallingConvention
};
foreach (var parameter in self.Parameters) {
reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
}
foreach (var genericParam in self.GenericParameters) {
reference.GenericParameters.Add(new GenericParameter(genericParam.Name, reference));
}
return reference;
}