2013-05-08 10 views
7

मैं देख रहे हैं, एक विधि है कि एक System.Lazy को दर्शाता है फेंकना करने की कोशिश कर रहा हूँ और लाइन newobj instance void class [mscorlib]System.Lazy`1<class Example.ExpensiveType>::.ctor(class [mscorlib]System.Func`1<class Example.ExpensiveType>)उत्सर्जन Mono.Cecil

पर "अमान्य टोकन" का एक PEVerify त्रुटि के साथ विफल साथ System.Lazy निर्माता करने के लिए कॉल ILDASM साथ कहीं और, मुझे लगता है कि एक उचित कॉल इस प्रकार दिखाई देगा:

newobj  instance void class [mscorlib]System.Lazy`1<class Example.IHeater>::.ctor(class [mscorlib]System.Func`1<!0>) 

दुर्भाग्य से, मैं कैसे Mono.Cecil एपीआई के साथ इस पुन: पेश करने के लिए के रूप में एक नुकसान में हूँ। क्या कोई जेनेरिक के साथ मदद कर सकता है?

यहाँ मैं अब तक है:

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

किसी भी मदद की बहुत सराहना की जाएगी - मैं स्टंप्डया रहा हूँ!

उत्तर

9

मुझे एक साल पुरानी मेलिंग सूची संग्रह में दफन किया गया जवाब मिला है (गैबर कोज़र! धन्यवाद।)। मैं सामान्य प्रकार और उनके तरीकों को सही ढंग से बनाने/आयात नहीं कर रहा था। कोड है जो ठीक से 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; 
} 
के रूप में परिभाषित किया जाता है
संबंधित मुद्दे