AssemblyBuilder.Save 메서드
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
이 동적 어셈블리를 디스크에 저장합니다.
오버로드
Save(String) |
이 동적 어셈블리를 디스크에 저장합니다. |
Save(String, PortableExecutableKinds, ImageFileMachine) |
이 동적 어셈블리를 디스크에 저장하고, 어셈블리의 실행 파일 및 대상 플랫폼에 코드의 특성을 지정합니다. |
Save(String)
- Source:
- AssemblyBuilder.cs
이 동적 어셈블리를 디스크에 저장합니다.
public:
void Save(System::String ^ assemblyFileName);
public void Save (string assemblyFileName);
member this.Save : string -> unit
Public Sub Save (assemblyFileName As String)
매개 변수
- assemblyFileName
- String
어셈블리의 파일 이름입니다.
예외
assemblyFileName
의 길이가 0입니다.
또는
어셈블리에 동일한 이름의 모듈 리소스 파일이 두 개 이상 있는 경우
또는
어셈블리의 대상 디렉터리가 잘못된 경우
또는
assemblyFileName
이 단순한 파일 이름이 아니거나(예: 디렉터리 또는 드라이브 구성 요소 있음), 이 어셈블리에 둘 이상의 관리되지 않는 리소스(버전 정보 리소스 포함)가 정의되어 있습니다.
또는
CultureInfo
의 AssemblyCultureAttribute 문자열이 유효한 문자열이 아니거나 DefineVersionInfoResource(String, String, String, String, String) 가 이 메서드 호출 전에 호출되었습니다.
assemblyFileName
이(가) null
인 경우
저장하는 동안 출력 오류가 발생한 경우
어셈블리의 모듈에 있는 형식이 디스크에 기록되도록CreateType() 이 호출되지 않았습니다.
예제
다음 코드 샘플에서는 동적 어셈블리를 만든 다음 를 사용하여 Save
로컬 디스크에 유지합니다.
using namespace System;
using namespace System::Text;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
// The Point class is the class we will reflect on and copy into our
// dynamic assembly. The public static function PointMain() will be used
// as our entry point.
//
// We are constructing the type seen here dynamically, and will write it
// out into a .exe file for later execution from the command-line.
// ---
// __gc class Point {
//
// private:
// int x;
// int y;
//
// public:
// Point(int ix, int iy) {
//
// this->x = ix;
// this->y = iy;
//
// }
//
// int DotProduct (Point* p) {
//
// return ((this->x * p->x) + (this->y * p->y));
//
// }
//
// static void PointMain() {
//
// Console::Write(S"Enter the 'x' value for point 1: ");
// int x1 = Convert::ToInt32(Console::ReadLine());
//
// Console::Write(S"Enter the 'y' value for point 1: ");
// int y1 = Convert::ToInt32(Console::ReadLine());
//
// Console::Write(S"Enter the 'x' value for point 2: ");
// int x2 = Convert::ToInt32(Console::ReadLine());
//
// Console::Write(S"Enter the 'y' value for point 2: ");
// int y2 = Convert::ToInt32(Console::ReadLine());
//
// Point* p1 = new Point(x1, y1);
// Point* p2 = new Point(x2, y2);
//
// Console::WriteLine(S"( {0}, {1}) . ( {2}, {3}) = {4}.",
// __box(x1), __box(y1), __box(x2), __box(y2), p1->DotProduct(p2));
//
// }
//
// };
// ---
Type^ BuildDynAssembly()
{
Type^ pointType = nullptr;
AppDomain^ currentDom = Thread::GetDomain();
Console::Write( "Please enter a name for your new assembly: " );
StringBuilder^ asmFileNameBldr = gcnew StringBuilder;
asmFileNameBldr->Append( Console::ReadLine() );
asmFileNameBldr->Append( ".exe" );
String^ asmFileName = asmFileNameBldr->ToString();
AssemblyName^ myAsmName = gcnew AssemblyName;
myAsmName->Name = "MyDynamicAssembly";
AssemblyBuilder^ myAsmBldr = currentDom->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::RunAndSave );
// We've created a dynamic assembly space - now, we need to create a module
// within it to reflect the type Point into.
ModuleBuilder^ myModuleBldr = myAsmBldr->DefineDynamicModule( asmFileName, asmFileName );
TypeBuilder^ myTypeBldr = myModuleBldr->DefineType( "Point" );
FieldBuilder^ xField = myTypeBldr->DefineField( "x", int::typeid, FieldAttributes::Private );
FieldBuilder^ yField = myTypeBldr->DefineField( "y", int::typeid, FieldAttributes::Private );
// Build the constructor.
Type^ objType = Type::GetType( "System.Object" );
ConstructorInfo^ objCtor = objType->GetConstructor( gcnew array<Type^>(0) );
array<Type^>^temp4 = {int::typeid,int::typeid};
array<Type^>^ctorParams = temp4;
ConstructorBuilder^ pointCtor = myTypeBldr->DefineConstructor( MethodAttributes::Public, CallingConventions::Standard, ctorParams );
ILGenerator^ ctorIL = pointCtor->GetILGenerator();
ctorIL->Emit( OpCodes::Ldarg_0 );
ctorIL->Emit( OpCodes::Call, objCtor );
ctorIL->Emit( OpCodes::Ldarg_0 );
ctorIL->Emit( OpCodes::Ldarg_1 );
ctorIL->Emit( OpCodes::Stfld, xField );
ctorIL->Emit( OpCodes::Ldarg_0 );
ctorIL->Emit( OpCodes::Ldarg_2 );
ctorIL->Emit( OpCodes::Stfld, yField );
ctorIL->Emit( OpCodes::Ret );
// Build the DotProduct method.
Console::WriteLine( "Constructor built." );
array<Type^>^temp0 = {myTypeBldr};
MethodBuilder^ pointDPBldr = myTypeBldr->DefineMethod( "DotProduct", MethodAttributes::Public, int::typeid, temp0 );
ILGenerator^ dpIL = pointDPBldr->GetILGenerator();
dpIL->Emit( OpCodes::Ldarg_0 );
dpIL->Emit( OpCodes::Ldfld, xField );
dpIL->Emit( OpCodes::Ldarg_1 );
dpIL->Emit( OpCodes::Ldfld, xField );
dpIL->Emit( OpCodes::Mul_Ovf_Un );
dpIL->Emit( OpCodes::Ldarg_0 );
dpIL->Emit( OpCodes::Ldfld, yField );
dpIL->Emit( OpCodes::Ldarg_1 );
dpIL->Emit( OpCodes::Ldfld, yField );
dpIL->Emit( OpCodes::Mul_Ovf_Un );
dpIL->Emit( OpCodes::Add_Ovf_Un );
dpIL->Emit( OpCodes::Ret );
// Build the PointMain method.
Console::WriteLine( "DotProduct built." );
MethodBuilder^ pointMainBldr = myTypeBldr->DefineMethod( "PointMain", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), void::typeid, nullptr );
pointMainBldr->InitLocals = true;
ILGenerator^ pmIL = pointMainBldr->GetILGenerator();
// We have four methods that we wish to call, and must represent as
// MethodInfo tokens:
// - void Console::WriteLine(String*)
// - String* Console::ReadLine()
// - int Convert::Int32(String*)
// - void Console::WriteLine(String*, Object*[])
array<Type^>^temp1 = {String::typeid};
MethodInfo^ writeMI = Console::typeid->GetMethod( "Write", temp1 );
MethodInfo^ readLineMI = Console::typeid->GetMethod( "ReadLine", gcnew array<Type^>(0) );
array<Type^>^temp2 = {String::typeid};
MethodInfo^ convertInt32MI = Convert::typeid->GetMethod( "ToInt32", temp2 );
array<Type^>^temp5 = {String::typeid,array<Object^>::typeid};
array<Type^>^wlParams = temp5;
MethodInfo^ writeLineMI = Console::typeid->GetMethod( "WriteLine", wlParams );
// Although we could just refer to the local variables by
// index (short ints for Ldloc/Stloc, bytes for LdLoc_S/Stloc_S),
// this time, we'll use LocalBuilders for clarity and to
// demonstrate their usage and syntax.
LocalBuilder^ x1LB = pmIL->DeclareLocal( int::typeid );
LocalBuilder^ y1LB = pmIL->DeclareLocal( int::typeid );
LocalBuilder^ x2LB = pmIL->DeclareLocal( int::typeid );
LocalBuilder^ y2LB = pmIL->DeclareLocal( int::typeid );
LocalBuilder^ point1LB = pmIL->DeclareLocal( myTypeBldr );
LocalBuilder^ point2LB = pmIL->DeclareLocal( myTypeBldr );
LocalBuilder^ tempObjArrLB = pmIL->DeclareLocal( array<Object^>::typeid );
pmIL->Emit( OpCodes::Ldstr, "Enter the 'x' value for point 1: " );
pmIL->EmitCall( OpCodes::Call, writeMI, nullptr );
pmIL->EmitCall( OpCodes::Call, readLineMI, nullptr );
pmIL->EmitCall( OpCodes::Call, convertInt32MI, nullptr );
pmIL->Emit( OpCodes::Stloc, x1LB );
pmIL->Emit( OpCodes::Ldstr, "Enter the 'y' value for point 1: " );
pmIL->EmitCall( OpCodes::Call, writeMI, nullptr );
pmIL->EmitCall( OpCodes::Call, readLineMI, nullptr );
pmIL->EmitCall( OpCodes::Call, convertInt32MI, nullptr );
pmIL->Emit( OpCodes::Stloc, y1LB );
pmIL->Emit( OpCodes::Ldstr, "Enter the 'x' value for point 2: " );
pmIL->EmitCall( OpCodes::Call, writeMI, nullptr );
pmIL->EmitCall( OpCodes::Call, readLineMI, nullptr );
pmIL->EmitCall( OpCodes::Call, convertInt32MI, nullptr );
pmIL->Emit( OpCodes::Stloc, x2LB );
pmIL->Emit( OpCodes::Ldstr, "Enter the 'y' value for point 2: " );
pmIL->EmitCall( OpCodes::Call, writeMI, nullptr );
pmIL->EmitCall( OpCodes::Call, readLineMI, nullptr );
pmIL->EmitCall( OpCodes::Call, convertInt32MI, nullptr );
pmIL->Emit( OpCodes::Stloc, y2LB );
pmIL->Emit( OpCodes::Ldloc, x1LB );
pmIL->Emit( OpCodes::Ldloc, y1LB );
pmIL->Emit( OpCodes::Newobj, pointCtor );
pmIL->Emit( OpCodes::Stloc, point1LB );
pmIL->Emit( OpCodes::Ldloc, x2LB );
pmIL->Emit( OpCodes::Ldloc, y2LB );
pmIL->Emit( OpCodes::Newobj, pointCtor );
pmIL->Emit( OpCodes::Stloc, point2LB );
pmIL->Emit( OpCodes::Ldstr, "( {0}, {1}) . ( {2}, {3}) = {4}." );
pmIL->Emit( OpCodes::Ldc_I4_5 );
pmIL->Emit( OpCodes::Newarr, Object::typeid );
pmIL->Emit( OpCodes::Stloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldc_I4_0 );
pmIL->Emit( OpCodes::Ldloc, x1LB );
pmIL->Emit( OpCodes::Box, int::typeid );
pmIL->Emit( OpCodes::Stelem_Ref );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldc_I4_1 );
pmIL->Emit( OpCodes::Ldloc, y1LB );
pmIL->Emit( OpCodes::Box, int::typeid );
pmIL->Emit( OpCodes::Stelem_Ref );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldc_I4_2 );
pmIL->Emit( OpCodes::Ldloc, x2LB );
pmIL->Emit( OpCodes::Box, int::typeid );
pmIL->Emit( OpCodes::Stelem_Ref );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldc_I4_3 );
pmIL->Emit( OpCodes::Ldloc, y2LB );
pmIL->Emit( OpCodes::Box, int::typeid );
pmIL->Emit( OpCodes::Stelem_Ref );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->Emit( OpCodes::Ldc_I4_4 );
pmIL->Emit( OpCodes::Ldloc, point1LB );
pmIL->Emit( OpCodes::Ldloc, point2LB );
pmIL->EmitCall( OpCodes::Callvirt, pointDPBldr, nullptr );
pmIL->Emit( OpCodes::Box, int::typeid );
pmIL->Emit( OpCodes::Stelem_Ref );
pmIL->Emit( OpCodes::Ldloc, tempObjArrLB );
pmIL->EmitCall( OpCodes::Call, writeLineMI, nullptr );
pmIL->Emit( OpCodes::Ret );
Console::WriteLine( "PointMain (entry point) built." );
pointType = myTypeBldr->CreateType();
Console::WriteLine( "Type completed." );
myAsmBldr->SetEntryPoint( pointMainBldr );
myAsmBldr->Save( asmFileName );
Console::WriteLine( "Assembly saved as ' {0}'.", asmFileName );
Console::WriteLine( "Type ' {0}' at the prompt to run your new dynamically generated dot product calculator.", asmFileName );
// After execution, this program will have generated and written to disk,
// in the directory you executed it from, a program named
// <name_you_entered_here>.exe. You can run it by typing
// the name you gave it during execution, in the same directory where
// you executed this program.
return pointType;
}
int main()
{
Type^ myType = BuildDynAssembly();
Console::WriteLine( "---" );
// Let's invoke the type 'Point' created in our dynamic assembly.
array<Object^>^temp3 = {nullptr,nullptr};
Object^ ptInstance = Activator::CreateInstance( myType, temp3 );
myType->InvokeMember( "PointMain", BindingFlags::InvokeMethod, nullptr, ptInstance, gcnew array<Object^>(0) );
}
using System;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
// The Point class is the class we will reflect on and copy into our
// dynamic assembly. The public static function PointMain() will be used
// as our entry point.
//
// We are constructing the type seen here dynamically, and will write it
// out into a .exe file for later execution from the command-line.
// ---
// class Point {
//
// private int x;
// private int y;
//
// public Point(int ix, int iy) {
//
// this.x = ix;
// this.y = iy;
//
// }
//
// public int DotProduct (Point p) {
//
// return ((this.x * p.x) + (this.y * p.y));
//
// }
//
// public static void PointMain() {
//
// Console.Write("Enter the 'x' value for point 1: ");
// int x1 = Convert.ToInt32(Console.ReadLine());
//
// Console.Write("Enter the 'y' value for point 1: ");
// int y1 = Convert.ToInt32(Console.ReadLine());
//
// Console.Write("Enter the 'x' value for point 2: ");
// int x2 = Convert.ToInt32(Console.ReadLine());
//
// Console.Write("Enter the 'y' value for point 2: ");
// int y2 = Convert.ToInt32(Console.ReadLine());
//
// Point p1 = new Point(x1, y1);
// Point p2 = new Point(x2, y2);
//
// Console.WriteLine("({0}, {1}) . ({2}, {3}) = {4}.",
// x1, y1, x2, y2, p1.DotProduct(p2));
//
// }
//
// }
// ---
class AssemblyBuilderDemo {
public static Type BuildDynAssembly() {
Type pointType = null;
AppDomain currentDom = Thread.GetDomain();
Console.Write("Please enter a name for your new assembly: ");
StringBuilder asmFileNameBldr = new StringBuilder();
asmFileNameBldr.Append(Console.ReadLine());
asmFileNameBldr.Append(".exe");
string asmFileName = asmFileNameBldr.ToString();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.RunAndSave);
// We've created a dynamic assembly space - now, we need to create a module
// within it to reflect the type Point into.
ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule(asmFileName,
asmFileName);
TypeBuilder myTypeBldr = myModuleBldr.DefineType("Point");
FieldBuilder xField = myTypeBldr.DefineField("x", typeof(int),
FieldAttributes.Private);
FieldBuilder yField = myTypeBldr.DefineField("y", typeof(int),
FieldAttributes.Private);
// Build the constructor.
Type objType = Type.GetType("System.Object");
ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
Type[] ctorParams = new Type[] {typeof(int), typeof(int)};
ConstructorBuilder pointCtor = myTypeBldr.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
ctorParams);
ILGenerator ctorIL = pointCtor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Call, objCtor);
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_1);
ctorIL.Emit(OpCodes.Stfld, xField);
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_2);
ctorIL.Emit(OpCodes.Stfld, yField);
ctorIL.Emit(OpCodes.Ret);
// Build the DotProduct method.
Console.WriteLine("Constructor built.");
MethodBuilder pointDPBldr = myTypeBldr.DefineMethod("DotProduct",
MethodAttributes.Public,
typeof(int),
new Type[] {myTypeBldr});
ILGenerator dpIL = pointDPBldr.GetILGenerator();
dpIL.Emit(OpCodes.Ldarg_0);
dpIL.Emit(OpCodes.Ldfld, xField);
dpIL.Emit(OpCodes.Ldarg_1);
dpIL.Emit(OpCodes.Ldfld, xField);
dpIL.Emit(OpCodes.Mul_Ovf_Un);
dpIL.Emit(OpCodes.Ldarg_0);
dpIL.Emit(OpCodes.Ldfld, yField);
dpIL.Emit(OpCodes.Ldarg_1);
dpIL.Emit(OpCodes.Ldfld, yField);
dpIL.Emit(OpCodes.Mul_Ovf_Un);
dpIL.Emit(OpCodes.Add_Ovf_Un);
dpIL.Emit(OpCodes.Ret);
// Build the PointMain method.
Console.WriteLine("DotProduct built.");
MethodBuilder pointMainBldr = myTypeBldr.DefineMethod("PointMain",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(void),
null);
pointMainBldr.InitLocals = true;
ILGenerator pmIL = pointMainBldr.GetILGenerator();
// We have four methods that we wish to call, and must represent as
// MethodInfo tokens:
// - void Console.WriteLine(string)
// - string Console.ReadLine()
// - int Convert.Int32(string)
// - void Console.WriteLine(string, object[])
MethodInfo writeMI = typeof(Console).GetMethod(
"Write",
new Type[] {typeof(string)});
MethodInfo readLineMI = typeof(Console).GetMethod(
"ReadLine",
new Type[0]);
MethodInfo convertInt32MI = typeof(Convert).GetMethod(
"ToInt32",
new Type[] {typeof(string)});
Type[] wlParams = new Type[] {typeof(string), typeof(object[])};
MethodInfo writeLineMI = typeof(Console).GetMethod(
"WriteLine",
wlParams);
// Although we could just refer to the local variables by
// index (short ints for Ldloc/Stloc, bytes for LdLoc_S/Stloc_S),
// this time, we'll use LocalBuilders for clarity and to
// demonstrate their usage and syntax.
LocalBuilder x1LB = pmIL.DeclareLocal(typeof(int));
LocalBuilder y1LB = pmIL.DeclareLocal(typeof(int));
LocalBuilder x2LB = pmIL.DeclareLocal(typeof(int));
LocalBuilder y2LB = pmIL.DeclareLocal(typeof(int));
LocalBuilder point1LB = pmIL.DeclareLocal(myTypeBldr);
LocalBuilder point2LB = pmIL.DeclareLocal(myTypeBldr);
LocalBuilder tempObjArrLB = pmIL.DeclareLocal(typeof(object[]));
pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 1: ");
pmIL.EmitCall(OpCodes.Call, writeMI, null);
pmIL.EmitCall(OpCodes.Call, readLineMI, null);
pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
pmIL.Emit(OpCodes.Stloc, x1LB);
pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 1: ");
pmIL.EmitCall(OpCodes.Call, writeMI, null);
pmIL.EmitCall(OpCodes.Call, readLineMI, null);
pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
pmIL.Emit(OpCodes.Stloc, y1LB);
pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 2: ");
pmIL.EmitCall(OpCodes.Call, writeMI, null);
pmIL.EmitCall(OpCodes.Call, readLineMI, null);
pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
pmIL.Emit(OpCodes.Stloc, x2LB);
pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 2: ");
pmIL.EmitCall(OpCodes.Call, writeMI, null);
pmIL.EmitCall(OpCodes.Call, readLineMI, null);
pmIL.EmitCall(OpCodes.Call, convertInt32MI, null);
pmIL.Emit(OpCodes.Stloc, y2LB);
pmIL.Emit(OpCodes.Ldloc, x1LB);
pmIL.Emit(OpCodes.Ldloc, y1LB);
pmIL.Emit(OpCodes.Newobj, pointCtor);
pmIL.Emit(OpCodes.Stloc, point1LB);
pmIL.Emit(OpCodes.Ldloc, x2LB);
pmIL.Emit(OpCodes.Ldloc, y2LB);
pmIL.Emit(OpCodes.Newobj, pointCtor);
pmIL.Emit(OpCodes.Stloc, point2LB);
pmIL.Emit(OpCodes.Ldstr, "({0}, {1}) . ({2}, {3}) = {4}.");
pmIL.Emit(OpCodes.Ldc_I4_5);
pmIL.Emit(OpCodes.Newarr, typeof(Object));
pmIL.Emit(OpCodes.Stloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldc_I4_0);
pmIL.Emit(OpCodes.Ldloc, x1LB);
pmIL.Emit(OpCodes.Box, typeof(int));
pmIL.Emit(OpCodes.Stelem_Ref);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldc_I4_1);
pmIL.Emit(OpCodes.Ldloc, y1LB);
pmIL.Emit(OpCodes.Box, typeof(int));
pmIL.Emit(OpCodes.Stelem_Ref);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldc_I4_2);
pmIL.Emit(OpCodes.Ldloc, x2LB);
pmIL.Emit(OpCodes.Box, typeof(int));
pmIL.Emit(OpCodes.Stelem_Ref);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldc_I4_3);
pmIL.Emit(OpCodes.Ldloc, y2LB);
pmIL.Emit(OpCodes.Box, typeof(int));
pmIL.Emit(OpCodes.Stelem_Ref);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.Emit(OpCodes.Ldc_I4_4);
pmIL.Emit(OpCodes.Ldloc, point1LB);
pmIL.Emit(OpCodes.Ldloc, point2LB);
pmIL.EmitCall(OpCodes.Callvirt, pointDPBldr, null);
pmIL.Emit(OpCodes.Box, typeof(int));
pmIL.Emit(OpCodes.Stelem_Ref);
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB);
pmIL.EmitCall(OpCodes.Call, writeLineMI, null);
pmIL.Emit(OpCodes.Ret);
Console.WriteLine("PointMain (entry point) built.");
pointType = myTypeBldr.CreateType();
Console.WriteLine("Type completed.");
myAsmBldr.SetEntryPoint(pointMainBldr);
myAsmBldr.Save(asmFileName);
Console.WriteLine("Assembly saved as '{0}'.", asmFileName);
Console.WriteLine("Type '{0}' at the prompt to run your new " +
"dynamically generated dot product calculator.",
asmFileName);
// After execution, this program will have generated and written to disk,
// in the directory you executed it from, a program named
// <name_you_entered_here>.exe. You can run it by typing
// the name you gave it during execution, in the same directory where
// you executed this program.
return pointType;
}
public static void Main() {
Type myType = BuildDynAssembly();
Console.WriteLine("---");
// Let's invoke the type 'Point' created in our dynamic assembly.
object ptInstance = Activator.CreateInstance(myType, new object[] {0,0});
myType.InvokeMember("PointMain",
BindingFlags.InvokeMethod,
null,
ptInstance,
new object[0]);
}
}
Imports System.Text
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
' The Point class is the class we will reflect on and copy into our
' dynamic assembly. The public static function PointMain() will be used
' as our entry point.
'
' We are constructing the type seen here dynamically, and will write it
' out into a .exe file for later execution from the command-line.
' ---
' Class Point
'
' Private x As Integer
' Private y As Integer
'
'
' Public Sub New(ix As Integer, iy As Integer)
'
' Me.x = ix
' Me.y = iy
' End Sub
'
'
' Public Function DotProduct(p As Point) As Integer
'
' Return Me.x * p.x + Me.y * p.y
' End Function 'DotProduct
'
'
' Public Shared Sub Main()
'
' Console.Write("Enter the 'x' value for point 1: ")
' Dim x1 As Integer = Convert.ToInt32(Console.ReadLine())
'
' Console.Write("Enter the 'y' value for point 1: ")
' Dim y1 As Integer = Convert.ToInt32(Console.ReadLine())
'
' Console.Write("Enter the 'x' value for point 2: ")
' Dim x2 As Integer = Convert.ToInt32(Console.ReadLine())
'
' Console.Write("Enter the 'y' value for point 2: ")
' Dim y2 As Integer = Convert.ToInt32(Console.ReadLine())
'
' Dim p1 As New Point(x1, y1)
' Dim p2 As New Point(x2, y2)
'
' Console.WriteLine("({0}, {1}) . ({2}, {3}) = {4}.", x1, y1, x2, y2, p1.DotProduct(p2))
' End Sub
' End Class
' ---
Class AssemblyBuilderDemo
Public Shared Function BuildDynAssembly() As Type
Dim pointType As Type = Nothing
Dim currentDom As AppDomain = Thread.GetDomain()
Console.Write("Please enter a name for your new assembly: ")
Dim asmFileNameBldr As New StringBuilder()
asmFileNameBldr.Append(Console.ReadLine())
asmFileNameBldr.Append(".exe")
Dim asmFileName As String = asmFileNameBldr.ToString()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBldr As AssemblyBuilder = currentDom.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.RunAndSave)
' We've created a dynamic assembly space - now, we need to create a module
' within it to reflect the type Point into.
Dim myModuleBldr As ModuleBuilder = myAsmBldr.DefineDynamicModule(asmFileName, _
asmFileName)
Dim myTypeBldr As TypeBuilder = myModuleBldr.DefineType("Point")
Dim xField As FieldBuilder = myTypeBldr.DefineField("x", GetType(Integer), _
FieldAttributes.Private)
Dim yField As FieldBuilder = myTypeBldr.DefineField("y", GetType(Integer), _
FieldAttributes.Private)
' Build the constructor.
Dim objType As Type = Type.GetType("System.Object")
Dim objCtor As ConstructorInfo = objType.GetConstructor(New Type() {})
Dim ctorParams() As Type = {GetType(Integer), GetType(Integer)}
Dim pointCtor As ConstructorBuilder = myTypeBldr.DefineConstructor( _
MethodAttributes.Public, _
CallingConventions.Standard, _
ctorParams)
Dim ctorIL As ILGenerator = pointCtor.GetILGenerator()
ctorIL.Emit(OpCodes.Ldarg_0)
ctorIL.Emit(OpCodes.Call, objCtor)
ctorIL.Emit(OpCodes.Ldarg_0)
ctorIL.Emit(OpCodes.Ldarg_1)
ctorIL.Emit(OpCodes.Stfld, xField)
ctorIL.Emit(OpCodes.Ldarg_0)
ctorIL.Emit(OpCodes.Ldarg_2)
ctorIL.Emit(OpCodes.Stfld, yField)
ctorIL.Emit(OpCodes.Ret)
' Build the DotProduct method.
Console.WriteLine("Constructor built.")
Dim pointDPBldr As MethodBuilder = myTypeBldr.DefineMethod("DotProduct", _
MethodAttributes.Public, _
GetType(Integer), _
New Type(0) {myTypeBldr})
Dim dpIL As ILGenerator = pointDPBldr.GetILGenerator()
dpIL.Emit(OpCodes.Ldarg_0)
dpIL.Emit(OpCodes.Ldfld, xField)
dpIL.Emit(OpCodes.Ldarg_1)
dpIL.Emit(OpCodes.Ldfld, xField)
dpIL.Emit(OpCodes.Mul_Ovf_Un)
dpIL.Emit(OpCodes.Ldarg_0)
dpIL.Emit(OpCodes.Ldfld, yField)
dpIL.Emit(OpCodes.Ldarg_1)
dpIL.Emit(OpCodes.Ldfld, yField)
dpIL.Emit(OpCodes.Mul_Ovf_Un)
dpIL.Emit(OpCodes.Add_Ovf_Un)
dpIL.Emit(OpCodes.Ret)
' Build the PointMain method.
Console.WriteLine("DotProduct built.")
Dim pointMainBldr As MethodBuilder = myTypeBldr.DefineMethod("PointMain", _
MethodAttributes.Public Or _
MethodAttributes.Static, _
Nothing, Nothing)
pointMainBldr.InitLocals = True
Dim pmIL As ILGenerator = pointMainBldr.GetILGenerator()
' We have four methods that we wish to call, and must represent as
' MethodInfo tokens:
' - Sub Console.WriteLine(string)
' - Function Console.ReadLine() As String
' - Function Convert.Int32(string) As Int
' - Sub Console.WriteLine(string, object[])
Dim writeMI As MethodInfo = GetType(Console).GetMethod("Write", _
New Type(0) {GetType(String)})
Dim readLineMI As MethodInfo = GetType(Console).GetMethod("ReadLine", _
New Type() {})
Dim convertInt32MI As MethodInfo = GetType(Convert).GetMethod("ToInt32", _
New Type(0) {GetType(String)})
Dim wlParams() As Type = {GetType(String), GetType(Object())}
Dim writeLineMI As MethodInfo = GetType(Console).GetMethod("WriteLine", wlParams)
' Although we could just refer to the local variables by
' index (short ints for Ldloc/Stloc, bytes for LdLoc_S/Stloc_S),
' this time, we'll use LocalBuilders for clarity and to
' demonstrate their usage and syntax.
Dim x1LB As LocalBuilder = pmIL.DeclareLocal(GetType(Integer))
Dim y1LB As LocalBuilder = pmIL.DeclareLocal(GetType(Integer))
Dim x2LB As LocalBuilder = pmIL.DeclareLocal(GetType(Integer))
Dim y2LB As LocalBuilder = pmIL.DeclareLocal(GetType(Integer))
Dim point1LB As LocalBuilder = pmIL.DeclareLocal(myTypeBldr)
Dim point2LB As LocalBuilder = pmIL.DeclareLocal(myTypeBldr)
Dim tempObjArrLB As LocalBuilder = pmIL.DeclareLocal(GetType(Object()))
pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 1: ")
pmIL.EmitCall(OpCodes.Call, writeMI, Nothing)
pmIL.EmitCall(OpCodes.Call, readLineMI, Nothing)
pmIL.EmitCall(OpCodes.Call, convertInt32MI, Nothing)
pmIL.Emit(OpCodes.Stloc, x1LB)
pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 1: ")
pmIL.EmitCall(OpCodes.Call, writeMI, Nothing)
pmIL.EmitCall(OpCodes.Call, readLineMI, Nothing)
pmIL.EmitCall(OpCodes.Call, convertInt32MI, Nothing)
pmIL.Emit(OpCodes.Stloc, y1LB)
pmIL.Emit(OpCodes.Ldstr, "Enter the 'x' value for point 2: ")
pmIL.EmitCall(OpCodes.Call, writeMI, Nothing)
pmIL.EmitCall(OpCodes.Call, readLineMI, Nothing)
pmIL.EmitCall(OpCodes.Call, convertInt32MI, Nothing)
pmIL.Emit(OpCodes.Stloc, x2LB)
pmIL.Emit(OpCodes.Ldstr, "Enter the 'y' value for point 2: ")
pmIL.EmitCall(OpCodes.Call, writeMI, Nothing)
pmIL.EmitCall(OpCodes.Call, readLineMI, Nothing)
pmIL.EmitCall(OpCodes.Call, convertInt32MI, Nothing)
pmIL.Emit(OpCodes.Stloc, y2LB)
pmIL.Emit(OpCodes.Ldloc, x1LB)
pmIL.Emit(OpCodes.Ldloc, y1LB)
pmIL.Emit(OpCodes.Newobj, pointCtor)
pmIL.Emit(OpCodes.Stloc, point1LB)
pmIL.Emit(OpCodes.Ldloc, x2LB)
pmIL.Emit(OpCodes.Ldloc, y2LB)
pmIL.Emit(OpCodes.Newobj, pointCtor)
pmIL.Emit(OpCodes.Stloc, point2LB)
pmIL.Emit(OpCodes.Ldstr, "({0}, {1}) . ({2}, {3}) = {4}.")
pmIL.Emit(OpCodes.Ldc_I4_5)
pmIL.Emit(OpCodes.Newarr, GetType([Object]))
pmIL.Emit(OpCodes.Stloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldc_I4_0)
pmIL.Emit(OpCodes.Ldloc, x1LB)
pmIL.Emit(OpCodes.Box, GetType(Integer))
pmIL.Emit(OpCodes.Stelem_Ref)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldc_I4_1)
pmIL.Emit(OpCodes.Ldloc, y1LB)
pmIL.Emit(OpCodes.Box, GetType(Integer))
pmIL.Emit(OpCodes.Stelem_Ref)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldc_I4_2)
pmIL.Emit(OpCodes.Ldloc, x2LB)
pmIL.Emit(OpCodes.Box, GetType(Integer))
pmIL.Emit(OpCodes.Stelem_Ref)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldc_I4_3)
pmIL.Emit(OpCodes.Ldloc, y2LB)
pmIL.Emit(OpCodes.Box, GetType(Integer))
pmIL.Emit(OpCodes.Stelem_Ref)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.Emit(OpCodes.Ldc_I4_4)
pmIL.Emit(OpCodes.Ldloc, point1LB)
pmIL.Emit(OpCodes.Ldloc, point2LB)
pmIL.EmitCall(OpCodes.Callvirt, pointDPBldr, Nothing)
pmIL.Emit(OpCodes.Box, GetType(Integer))
pmIL.Emit(OpCodes.Stelem_Ref)
pmIL.Emit(OpCodes.Ldloc, tempObjArrLB)
pmIL.EmitCall(OpCodes.Call, writeLineMI, Nothing)
pmIL.Emit(OpCodes.Ret)
Console.WriteLine("PointMain (entry point) built.")
pointType = myTypeBldr.CreateType()
Console.WriteLine("Type completed.")
myAsmBldr.SetEntryPoint(pointMainBldr)
myAsmBldr.Save(asmFileName)
Console.WriteLine("Assembly saved as '{0}'.", asmFileName)
Console.WriteLine("Type '{0}' at the prompt to run your new " + "dynamically generated dot product calculator.", asmFileName)
' After execution, this program will have generated and written to disk,
' in the directory you executed it from, a program named
' <name_you_entered_here>.exe. You can run it by typing
' the name you gave it during execution, in the same directory where
' you executed this program.
Return pointType
End Function 'BuildDynAssembly
Public Shared Sub Main()
Dim myType As Type = BuildDynAssembly()
Console.WriteLine("---")
' Let's invoke the type 'Point' created in our dynamic assembly.
Dim ptInstance As Object = Activator.CreateInstance(myType, New Object(1) {0, 0})
myType.InvokeMember("PointMain", BindingFlags.InvokeMethod, _
Nothing, ptInstance, New Object() {})
End Sub
End Class
설명
참고
동적 어셈블리를 디스크에 저장하는 것은 .NET Framework 지원됩니다.
이 메서드는 이 동적 어셈블리에 정의된 모든 일시적이지 않은 동적 모듈을 저장합니다. 일시적인 동적 모듈은 저장되지 않습니다. 어셈블리 파일 이름은 모듈 중 하나의 이름과 같을 수 있습니다. 이 경우 어셈블리 매니페스트는 해당 모듈 내에 저장됩니다.
assemblyFileName
는 어셈블리에 포함된 모든 모듈의 이름과 다를 수 있습니다. 이 경우 어셈블리 파일에는 어셈블리 매니페스트만 포함됩니다.
를 사용하여 DefineResource얻은 각 ResourceWriter 에 대해 이 메서드는 .resources 파일을 작성하고 를 호출 Close 하여 스트림을 닫습니다.
는 assemblyFileName
드라이브 또는 디렉터리 구성 요소가 없는 간단한 파일 이름이어야 합니다. 특정 디렉터리에 어셈블리를 만들려면 대상 디렉터리 인수를 DefineDynamicAssembly 사용하는 메서드 중 하나를 사용합니다.
.NET Framework 버전 2.0에서 메서드의 Save 이 오버로드는 매개 변수 및 I386 매개 변수에 대해 portableExecutableKind
메서드 오버로드 ILOnly 를 호출 Save(String, PortableExecutableKinds, ImageFileMachine) 하는 imageFileMachine
것과 같습니다.
적용 대상
Save(String, PortableExecutableKinds, ImageFileMachine)
이 동적 어셈블리를 디스크에 저장하고, 어셈블리의 실행 파일 및 대상 플랫폼에 코드의 특성을 지정합니다.
public:
void Save(System::String ^ assemblyFileName, System::Reflection::PortableExecutableKinds portableExecutableKind, System::Reflection::ImageFileMachine imageFileMachine);
public void Save (string assemblyFileName, System.Reflection.PortableExecutableKinds portableExecutableKind, System.Reflection.ImageFileMachine imageFileMachine);
member this.Save : string * System.Reflection.PortableExecutableKinds * System.Reflection.ImageFileMachine -> unit
Public Sub Save (assemblyFileName As String, portableExecutableKind As PortableExecutableKinds, imageFileMachine As ImageFileMachine)
매개 변수
- assemblyFileName
- String
어셈블리의 파일 이름입니다.
- portableExecutableKind
- PortableExecutableKinds
코드의 특성을 지정하는 비교할 PortableExecutableKinds 값의 비트 조합입니다.
- imageFileMachine
- ImageFileMachine
대상 플랫폼을 지정하는 ImageFileMachine 값 중 하나입니다.
예외
assemblyFileName
의 길이가 0입니다.
또는
어셈블리에 동일한 이름의 모듈 리소스 파일이 두 개 이상 있는 경우
또는
어셈블리의 대상 디렉터리가 잘못된 경우
또는
assemblyFileName
이 단순한 파일 이름이 아니거나(예: 디렉터리 또는 드라이브 구성 요소 있음), 이 어셈블리에 둘 이상의 관리되지 않는 리소스(버전 정보 리소스 포함)가 정의되어 있습니다.
또는
CultureInfo
의 AssemblyCultureAttribute 문자열이 유효한 문자열이 아니거나 DefineVersionInfoResource(String, String, String, String, String) 가 이 메서드 호출 전에 호출되었습니다.
assemblyFileName
이(가) null
인 경우
저장하는 동안 출력 오류가 발생한 경우
어셈블리의 모듈에 있는 형식이 디스크에 기록되도록CreateType() 이 호출되지 않았습니다.
설명
참고
동적 어셈블리를 디스크에 저장하는 것은 .NET Framework 지원됩니다.
및 portableExecutableKind
가 호환되지 않는 경우 imageFileMachine
가 imageFileMachine
보다 portableExecutableKind
우선합니다. 예외는 throw되지 않습니다. 예를 들어 로 를 지정 ImageFileMachine.I386PortableExecutableKinds.PE32PlusPortableExecutableKinds.PE32Plus 하면 이 무시됩니다.
이 메서드는 이 동적 어셈블리에 정의된 모든 일시적이지 않은 동적 모듈을 저장합니다. 일시적인 동적 모듈은 저장되지 않습니다. 어셈블리 파일 이름은 모듈 중 하나의 이름과 같을 수 있습니다. 이 경우 어셈블리 매니페스트는 해당 모듈 내에 저장됩니다.
assemblyFileName
는 어셈블리에 포함된 모든 모듈의 이름과 다를 수 있습니다. 이 경우 어셈블리 파일에는 어셈블리 매니페스트만 포함됩니다.
를 사용하여 DefineResource얻은 각 ResourceWriter 에 대해 이 메서드는 .resources 파일을 작성하고 를 호출 Close 하여 스트림을 닫습니다.
는 assemblyFileName
드라이브 또는 디렉터리 구성 요소가 없는 간단한 파일 이름이어야 합니다. 특정 디렉터리에 어셈블리를 만들려면 대상 디렉터리 인수를 DefineDynamicAssembly 사용하는 메서드 중 하나를 사용합니다.
적용 대상
.NET