AssemblyBuilder.Save メソッド
定義
重要
一部の情報は、リリース前に大きく変更される可能性があるプレリリースされた製品に関するものです。 Microsoft は、ここに記載されている情報について、明示または黙示を問わず、一切保証しません。
ディスクにこの動的アセンブリを保存します。
オーバーロード
Save(String) |
ディスクにこの動的アセンブリを保存します。 |
Save(String, PortableExecutableKinds, ImageFileMachine) |
ディスクにこの動的アセンブリを保存します。その際、アセンブリの実行可能ファイルのコードの性質とターゲット プラットフォームを指定します。 |
Save(String)
ディスクにこの動的アセンブリを保存します。
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 です。
- または -
アセンブリに同じ名前のモジュール リソース ファイルが 2 つ以上あります。
- または -
アセンブリのターゲット ディレクトリが正しくありません。
- または -
assemblyFileName
が単純なファイル名 (たとえば、ディレクトリまたはドライブのコンポーネントを持つ) でないか、複数のアンマネージ リソース (バージョン情報のリソースを含む) がこのアセンブリで定義されています。
- または -
AssemblyCultureAttribute の CultureInfo
文字列が有効な文字列ではなく、かつ、このメソッドを呼び出す前に 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でのみサポートされています。
このメソッドは、この動的アセンブリで定義されているすべての非一時的な動的モジュールを保存します。 一時的な動的モジュールは保存されません。 アセンブリ ファイル名は、モジュールの 1 つの名前と同じにすることができます。 その場合、アセンブリ マニフェストはそのモジュール内に格納されます。
assemblyFileName
は、アセンブリ内に含まれるすべてのモジュールの名前とは異なる場合があります。 その場合、アセンブリ ファイルにはアセンブリ マニフェストのみが含まれます。
を使用してDefineResource取得したごとにResourceWriter、このメソッドは .resources ファイルを書き込み、 を呼び出Closeしてストリームを閉じます。
は assemblyFileName
、ドライブまたはディレクトリ コンポーネントのない単純なファイル名である必要があります。 特定のディレクトリにアセンブリを作成するには、ターゲット ディレクトリ引数を DefineDynamicAssembly 受け取るメソッドのいずれかを使用します。
.NET Framework バージョン 2.0 では、 メソッドのSaveこのオーバーロードは、 パラメーターと パラメーターの Save(String, PortableExecutableKinds, ImageFileMachine) メソッド オーバーロードを ILOnlyportableExecutableKind
呼び出すこととI386imageFileMachine
同じです。
適用対象
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 の値の 1 つ。
例外
assemblyFileName
の長さは 0 です。
- または -
アセンブリに同じ名前のモジュール リソース ファイルが 2 つ以上あります。
- または -
アセンブリのターゲット ディレクトリが正しくありません。
- または -
assemblyFileName
が単純なファイル名 (たとえば、ディレクトリまたはドライブのコンポーネントを持つ) でないか、複数のアンマネージ リソース (バージョン情報のリソースを含む) がこのアセンブリで定義されています。
- または -
AssemblyCultureAttribute の CultureInfo
文字列が有効な文字列ではなく、かつ、このメソッドを呼び出す前に DefineVersionInfoResource(String, String, String, String, String) が呼び出されました。
assemblyFileName
が null
です。
保存中に出力エラーが発生します。
ディスクに書き込まれるアセンブリのモジュール内のいずれの型についても CreateType() が呼び出されませんでした。
注釈
注意
動的アセンブリをディスクに保存することは、.NET Frameworkでのみサポートされています。
と portableExecutableKind
が互換性がない場合imageFileMachine
は、 imageFileMachine
よりもportableExecutableKind
優先されます。 例外はスローされません。 たとえば、 で PortableExecutableKinds.PE32PlusPortableExecutableKinds.PE32Plus を指定ImageFileMachine.I386した場合は無視されます。
このメソッドは、この動的アセンブリで定義されているすべての非一時的な動的モジュールを保存します。 一時的な動的モジュールは保存されません。 アセンブリ ファイル名は、モジュールの 1 つの名前と同じにすることができます。 その場合、アセンブリ マニフェストはそのモジュール内に格納されます。
assemblyFileName
は、アセンブリ内に含まれるすべてのモジュールの名前とは異なる場合があります。 その場合、アセンブリ ファイルにはアセンブリ マニフェストのみが含まれます。
を使用してDefineResource取得したごとにResourceWriter、このメソッドは .resources ファイルを書き込み、 を呼び出Closeしてストリームを閉じます。
は assemblyFileName
、ドライブまたはディレクトリ コンポーネントのない単純なファイル名である必要があります。 特定のディレクトリにアセンブリを作成するには、ターゲット ディレクトリ引数を DefineDynamicAssembly 受け取るメソッドのいずれかを使用します。
適用対象
.NET