2011-12-06 8 views
2

.netアセンブリのビルドを示す多くのc#コードスニペットがあります。アセンブリを作成して保存する方法は?

コードは正常に実行されますが、保存されたアセンブリには生成されたコードが含まれていないという問題があります。 - 私はAssemblyBuilderのRunAndSaveプロパティを設定しています。

誰かが、正しく生成されたクラスやメソッドなどを使ってアセンブリを正しくビルドして保存する方法を教えてもらえますか?

ありがとうございます!

+0

どのコードを使用していますか? – ChrisBint

+1

何を試しましたか? AssemblyBuilder、ModuleBuilder、TypeBuilderなどが必要です。また、AssemblyBuilderを保存できるように設定する必要があります –

+0

MSDNには完全な例があります:http://msdn.microsoft.com/en-us/library/system.reflection.emit .assemblybuilder.aspx - 私は本当にリンクオンリーの回答を投稿したくないですが、それ以外のものは必要ありませんし、テキストをコピーすることは悪い考えです... –

答えて

3

私がデモで使用したコードは次のとおりです。簡単な例のために少しですが、それは動作します。保存はBuildGenericTypeメソッドで行われます。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection.Emit; 
using System.Reflection; 

namespace ReflectionEmit 
{ 
    class Program 
    { 
     delegate int DoMath(int value); 

     static DoMath mathFunc; 

     static void Main(string[] args) 
     { 
      CreateCode(27, true); 
      CreateCode(27, false); 

      BuildGenericType(); 

      Console.ReadKey(); 
     } 

     private static void CreateCode(int value, bool square) 
     { 
      mathFunc = (DoMath)BuildMethod(square).CreateDelegate(typeof(DoMath)); 
      int result = mathFunc(value); 

      Console.WriteLine("Result for {0} was {1}", value, result); 

     } 

     private static DynamicMethod BuildMethod(bool square) 
     { 
      Type[] methodArgs = { typeof(int) }; 
      DynamicMethod mthMeth = new DynamicMethod(
       "Square", 
       typeof(int), 
       methodArgs, 
       typeof(ReflectionEmit.Program).Module); 

      ILGenerator il = mthMeth.GetILGenerator(); 

      if (square) 
      { 
       il.Emit(OpCodes.Ldarg_0); //Loads argument at index 0 into the evaluation stack 
       il.Emit(OpCodes.Conv_I8); //Converts the value on top of the evaluation stack to int64 
       il.Emit(OpCodes.Dup); //Copies the top most value on the evaluation stack, then pushes it to the top 
       il.Emit(OpCodes.Mul); //Multiplies two values then pushes result to top of evaluation stack 
       il.Emit(OpCodes.Ret); //Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack. 
      } 
      else 
      { 
       il.Emit(OpCodes.Ldarg_0); //Loads argument at index 0 into the evaluation stack 
       il.Emit(OpCodes.Conv_I8); //Converts the value on top of the evaluation stack to int64 
       il.Emit(OpCodes.Dup); //Copies the top most value on the evaluation stack, then pushes it to the top 
       il.Emit(OpCodes.Add); //Adds two values then pushes result to top of evaluation stack 
       il.Emit(OpCodes.Ret); //Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack. 
      } 

      return mthMeth; 
     } 

     private static void BuildGenericType() 
     { 
      //Define assembly 
      AppDomain dom = AppDomain.CurrentDomain; 
      AssemblyName asmName = new AssemblyName("domath"); 
      AssemblyBuilder asm = dom.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); 

      //Define a dynamic module 
      ModuleBuilder mod = asm.DefineDynamicModule(asmName.Name, asmName.Name + ".dll"); 

      //Define a class 
      TypeBuilder asmType = mod.DefineType("OurClass", TypeAttributes.Public); 

      //Define the generic type parameters 
      string[] typeNames = { "TFirst", "TSecond" }; 
      GenericTypeParameterBuilder[] genTypes = asmType.DefineGenericParameters(typeNames); 

      GenericTypeParameterBuilder TFirst = genTypes[0]; 
      GenericTypeParameterBuilder TSecond = genTypes[1]; 

      //Define generic constraints 
      TFirst.SetGenericParameterAttributes(GenericParameterAttributes.DefaultConstructorConstraint | GenericParameterAttributes.ReferenceTypeConstraint); 
      TSecond.SetBaseTypeConstraint(typeof(SomeBaseClass)); 

      Type[] interfaceTypes = {typeof(InterfaceA), typeof(InterfaceB) }; 
      TSecond.SetInterfaceConstraints(interfaceTypes); 

      //Define a field 
      FieldBuilder fld1 = asmType.DefineField("Field1", TFirst, FieldAttributes.Private); 

      //Define method 
      Type listOf = typeof(List<>); 
      Type listOfTFirst = listOf.MakeGenericType(TFirst); 
      Type[] paramTypes = { TFirst.MakeArrayType() }; 

      MethodBuilder asmMethod = asmType.DefineMethod("SomeMethod", MethodAttributes.Public | MethodAttributes.Static, listOfTFirst, paramTypes); 

      //Define Method Body 
      ILGenerator il = asmMethod.GetILGenerator(); 

      Type ienumOf = typeof(IEnumerable<>); 
      Type tFromListOf = listOf.GetGenericArguments()[0]; 
      Type ienumOfT = ienumOf.MakeGenericType(tFromListOf); 
      Type[] ctorArgs = { ienumOfT }; 

      ConstructorInfo ctorPrep = listOf.GetConstructor(ctorArgs); 
      ConstructorInfo ctor = TypeBuilder.GetConstructor(listOfTFirst, ctorPrep); 

      il.Emit(OpCodes.Ldarg_0); //Loads the argument at index 0 onto the evaluation stack. 
      il.Emit(OpCodes.Newobj, ctor); //Creates a new object or a new instance of a value type, pushing an object reference (type O) onto the evaluation stack. 
      il.Emit(OpCodes.Ret); //Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack. 

      //Create type and save file 
      Type finished = asmType.CreateType(); 
      asm.Save(asmName.Name + ".dll"); 



     } 
    } 

    public interface InterfaceA { } 
    public interface InterfaceB { } 

    public class SomeBaseClass 
    { 

    } 
} 

代わりに、おそらくあなたはRosylnを試すことができますか? http://blogs.msdn.com/b/csharpfaq/archive/2011/12/02/introduction-to-the-roslyn-scripting-api.aspx

+0

ありがとう、それを試してみましょう。 – John

関連する問題