2011-02-11 4 views
5

나는 이전 질문 인 : Mono.Cecil: call base class' method from other assembly을 추적하고 있습니다.
동일한 일을하고 있지만 기본 클래스가 제네릭이면 작동하지 않습니다.Mono.Cecil : 다른 어셈블리에서 GENERIC 기본 클래스의 메서드 호출

//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) 

의 변화가 무엇을? 이전 포스트에서

+0

이 오히려 중요 해지고있다, 도와주세요!!! – TDaver

답변

16

당신은 당신과 같은 코드를 사용하고 있음을 나타냅니다 분명히

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, 당신은을 잃고있어 일반적인 인스턴스 생성 정보. 기본 유형의 적절한 일반 정보를 사용하여 적절한 메소드 호출을 다시 작성해야합니다. 일을 단순화하기 위해

는의가 세실의 테스트 스위트에서 가져온 다음과 같은 방법을 사용하자 : 그와

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

감사합니다. 작동 중입니다! – TDaver