2011-02-11 16 views
5

Daha önceki sorumu takip ediyorum: Mono.Cecil: call base class' method from other assembly.
Aynı şeyi yapıyorum ama temel sınıfım jenerikse işe yaramıyor.Mono.Cecil: GENERIC temel sınıf 'yöntemini diğer aksamdan arayın

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

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

Aşağıdaki kodu örgüleri:

L_000e: call instance void [AssemblyA]Base`1::RaisePropertyChanged(string) 

yerine

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

arasında değiştirmek için orada nedir? Önceki gönderide

+0

bu oldukça önemli olmaktadır, lütfen yardım et!!! – TDaver

cevap

16

Eğer böyle bir kod kullandığınızı gösterir: Açıkçası

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

, bu jenerik için uygun değildir:

Eğer Resolve() .BaseType, sen kaybediyorsun genel örnekleme bilgisi. Uygun yöntem çağrısını taban türünden uygun genel bilgilerle yeniden oluşturmanız gerekir. şeyleri basitleştirmek için

, Cecil test paketi alınan aşağıdaki yöntemleri, kullanalım: O ile

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; 
} 

, siz kodunuzu yeniden yazabilirsiniz:

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); 
+0

Teşekkürler, çalışıyor! – TDaver

İlgili konular