gpt4 book ai didi

generics - Mono.Cecil:从其他程序集中调用 GENERIC 基类的方法

转载 作者:行者123 更新时间:2023-12-04 13:10:07 30 4
gpt4 key购买 nike

我正在跟进我之前的问题:Mono.Cecil: call base class' method from other assembly .
我正在做同样的事情,但如果我的基类是通用的,它就不起作用。

//in Assembly A
class BaseVM<T> {}

//in Assembly B
class MyVM : Base<SomeModel> {
[NotifyProperty]
public string Something {get;set;}
}

它编织了以下代码:
L_000e: call instance void [AssemblyA]Base`1::RaisePropertyChanged(string)

代替
L_000e: call instance void [AssemblyA]Base`1<class SomeModel>::RaisePropertyChanged(string)

有什么可以改变的?

最佳答案

在您之前的帖子中,您指出您正在使用以下代码:

TypeDefinition type = ...;
TypeDefintion baseType = type.BaseType.Resolve ();
MethodDefinition baseMethod = baseType.Methods.First (m => ...);
MethodReference baseMethodReference = type.Module.Import (baseMethod);
il.Emit (OpCodes.Call, baseMethodReference);

显然,这不适合泛型:

当您 Resolve () .BaseType,您将丢失通用实例化信息。您需要使用来自基类型的适当泛型信息重新创建适当的方法调用。

为了简化事情,让我们使用以下方法,取自 Cecil 测试套件:

public static TypeReference MakeGenericType (this TypeReference self, params TypeReference [] arguments)
{
if (self.GenericParameters.Count != arguments.Length)
throw new ArgumentException ();

var instance = new GenericInstanceType (self);
foreach (var argument in arguments)
instance.GenericArguments.Add (argument);

return instance;
}

public static MethodReference MakeGeneric (this MethodReference self, params TypeReference [] arguments)
{
var reference = new MethodReference(self.Name,self.ReturnType) {
DeclaringType = self.DeclaringType.MakeGenericType (arguments),
HasThis = self.HasThis,
ExplicitThis = self.ExplicitThis,
CallingConvention = self.CallingConvention,
};

foreach (var parameter in self.Parameters)
reference.Parameters.Add (new ParameterDefinition (parameter.ParameterType));

foreach (var generic_parameter in self.GenericParameters)
reference.GenericParameters.Add (new GenericParameter (generic_parameter.Name, reference));

return reference;
}

有了这些,您可以将代码重写为:

TypeDefinition type = ...;
TypeDefintion baseTypeDefinition = type.BaseType.Resolve ();
MethodDefinition baseMethodDefinition = baseTypeDefinition.Methods.First (m => ...);
MethodReference baseMethodReference = type.Module.Import (baseMethodDefinition);
if (type.BaseType.IsGenericInstance) {
var baseTypeInstance = (GenericInstanceType) type.BaseType;
baseMethodReference = baseMethodReference.MakeGeneric (baseTypeInstance.GenericArguments.ToArray ());
}

il.Emit (OpCodes.Call, baseMethodReference);

关于generics - Mono.Cecil:从其他程序集中调用 GENERIC 基类的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4968755/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com