2016-11-28 11 views
2

は、私は次のようなプログラムにモノセシルを使用して、静的コンストラクタを追加しようとしています原因:Mono.Cecilと静的コンストラクタを追加するTypeInitializationException

namespace SimpleTarget 
{ 
    class C 
    { 
     public void M() 
     { 
      Console.WriteLine("Hello, World!"); 
     } 
    } 
} 

次のコードは、静的コンストラクタを追加します。

namespace AddStaticConstructor 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var assemblyPath = args[0]; 
      var module = ModuleDefinition.ReadModule(assemblyPath); 

      var corlib = ModuleDefinition.ReadModule(typeof(object).Module.FullyQualifiedName); 
      var method = corlib.Types.First(t => t.Name.Equals("Console")).Methods.First(m => m.Name.Contains("WriteLine")); 

      var methodToCall = module.Import(method); 

      foreach (var type in module.Types) 
      { 
       if (!type.Name.Contains("C")) continue; 

       var staticConstructorAttributes = 
        Mono.Cecil.MethodAttributes.Private | 
        Mono.Cecil.MethodAttributes.HideBySig | 
        Mono.Cecil.MethodAttributes.Static | 
        Mono.Cecil.MethodAttributes.SpecialName | 
        Mono.Cecil.MethodAttributes.RTSpecialName; 

       MethodDefinition staticConstructor = new MethodDefinition(".cctor", staticConstructorAttributes, module.TypeSystem.Void); 
       type.Methods.Add(staticConstructor); 

       type.IsBeforeFieldInit = false; 

       var il = staticConstructor.Body.GetILProcessor(); 
       il.Append(Instruction.Create(OpCodes.Ret)); 

       Instruction ldMethodName = il.Create(OpCodes.Ldstr, type.FullName); 
       Instruction callOurMethod = il.Create(OpCodes.Call, methodToCall); 

       Instruction firstInstruction = staticConstructor.Body.Instructions[0]; 
       // Inserts the callOurMethod instruction before the first instruction 


       il.InsertBefore(firstInstruction, ldMethodName); 
       il.InsertAfter(ldMethodName, callOurMethod); 
      } 

      module.Write(assemblyPath); 
     } 
    } 
} 

dotPeekでデコンパイルされたバイナリを見ると、すべてが正しく設定されているように見えます。 Cタイプを使用しようとすると、内部例外「System.InvalidProgramException:内部制限が発生しました:JITコンパイラが内部制限を検出しました」のTypeInitializationExceptionが発生します。

静的コンストラクタを使用する前に、

ありがとうございます!

var corlib = ModuleDefinition.ReadModule(typeof(object).Module.FullyQualifiedName); 
var method = corlib.Types.First(t => t.Name.Equals("Console")).Methods.First(m => m.Name.Contains("WriteLine")); 
var methodToCall = module.Import(method); 

使用この単純なコードは、使用する過負荷を得る:

+0

[MCVE]を投稿してくださいを。 –

答えて

2

問題は、あなたがここにSystem.WriteLineの間違ったオーバーロードを取得しているということである

var wlMethod = typeof (Console).GetMethod(nameof(Console.WriteLine), new[] {typeof (string)}); 
var methodToCall = module.ImportReference(wlMethod); 
+0

これは問題ではありません。はい、言及したように書く方が良いですが、彼が書いたようにも機能します。彼はちょうど最初の 'WriteLine'メソッドを持っていますが、引数を渡さなかったので問題はありません。 –

+0

'ldstr'で読み込んだ文字列を格納する必要はありません。単に使用することができます。 – thehennyy

+0

はい、使用しています。しかし、彼はしませんでした。 –

関連する問題