AssemblyBuilder.Save Metodo
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Salva l'assembly dinamico sul disco.
Overload
Save(String) |
Salva l'assembly dinamico sul disco. |
Save(String, PortableExecutableKinds, ImageFileMachine) |
Salva l'assembly dinamico su disco, specificando la natura del codice nei file eseguibili dell'assembly e la piattaforma di destinazione. |
Save(String)
- Origine:
- AssemblyBuilder.cs
Salva l'assembly dinamico sul disco.
public:
void Save(System::String ^ assemblyFileName);
public void Save (string assemblyFileName);
member this.Save : string -> unit
Public Sub Save (assemblyFileName As String)
Parametri
- assemblyFileName
- String
Nome file dell'assembly.
Eccezioni
La lunghezza di assemblyFileName
è 0.
-oppure-
L'assembly contiene due o più file di risorse dei moduli con lo stesso nome.
-oppure-
La directory di destinazione dell'assembly non è valida.
-oppure-
assemblyFileName
non è un nome file semplice, ad esempio un componente di unità o directory, oppure nell'assembly sono state definite più risorse non gestite, inclusa una risorsa di informazioni sulla versione.
-oppure-
La stringa CultureInfo
in AssemblyCultureAttribute non è valida e DefineVersionInfoResource(String, String, String, String, String) è stato chiamato prima di chiamare il metodo.
assemblyFileName
è null
.
Durante il salvataggio si verifica un errore di output.
Il metodo CreateType() non è stato chiamato per alcuno dei tipi nei moduli dell'assembly da scrivere nel disco.
Esempio
L'esempio di codice seguente crea un assembly dinamico e quindi lo rende persistente in un disco locale usando 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
Commenti
Nota
Il salvataggio di un assembly dinamico su disco è supportato solo in .NET Framework.
Questo metodo salva tutti i moduli dinamici non temporanei definiti in questo assembly dinamico. I moduli dinamici temporanei non vengono salvati. Il nome del file di assembly può essere uguale al nome di uno dei moduli. In tal caso, il manifesto dell'assembly viene archiviato all'interno di tale modulo.
assemblyFileName
può essere diverso dai nomi di tutti i moduli contenuti nell'assembly. In tal caso, il file di assembly contiene solo il manifesto dell'assembly.
Per ogni ResourceWriter oggetto ottenuto usando DefineResource, questo metodo scrive il file con estensione resources e chiama Close per chiudere il flusso.
Deve assemblyFileName
essere un nome di file semplice senza un'unità o un componente di directory. Per creare un assembly in una directory specifica, utilizzare uno dei DefineDynamicAssembly metodi che accettano un argomento della directory di destinazione.
In .NET Framework versione 2.0 questo overload del Save metodo equivale a chiamare l'overload Save(String, PortableExecutableKinds, ImageFileMachine) del metodo con ILOnly per il portableExecutableKind
parametro e I386 per il imageFileMachine
parametro .
Si applica a
Save(String, PortableExecutableKinds, ImageFileMachine)
Salva l'assembly dinamico su disco, specificando la natura del codice nei file eseguibili dell'assembly e la piattaforma di destinazione.
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)
Parametri
- assemblyFileName
- String
Nome file dell'assembly.
- portableExecutableKind
- PortableExecutableKinds
Combinazione bit per bit di valori di PortableExecutableKinds che specifica la natura del codice.
- imageFileMachine
- ImageFileMachine
Uno dei valori di ImageFileMachine che specifica la piattaforma di destinazione.
Eccezioni
La lunghezza di assemblyFileName
è 0.
-oppure-
L'assembly contiene due o più file di risorse dei moduli con lo stesso nome.
-oppure-
La directory di destinazione dell'assembly non è valida.
-oppure-
assemblyFileName
non è un nome file semplice, ad esempio include un componente di unità o directory, oppure nell'assembly sono state definite più risorse non gestite, inclusa una risorsa di informazioni sulla versione.
-oppure-
La stringa CultureInfo
in AssemblyCultureAttribute non è valida e DefineVersionInfoResource(String, String, String, String, String) è stato chiamato prima di chiamare il metodo.
assemblyFileName
è null
.
Durante il salvataggio si verifica un errore di output.
Il metodo CreateType() non è stato chiamato per alcuno dei tipi nei moduli dell'assembly da scrivere nel disco.
Commenti
Nota
Il salvataggio di un assembly dinamico su disco è supportato solo in .NET Framework.
Se imageFileMachine
e portableExecutableKind
sono incompatibili, imageFileMachine
ha la precedenza su portableExecutableKind
. Non viene generata alcuna eccezione. Ad esempio, se si specifica ImageFileMachine.I386 con PortableExecutableKinds.PE32Plus, PortableExecutableKinds.PE32Plus viene ignorato.
Questo metodo salva tutti i moduli dinamici non temporanei definiti in questo assembly dinamico. I moduli dinamici temporanei non vengono salvati. Il nome del file di assembly può essere uguale al nome di uno dei moduli. In tal caso, il manifesto dell'assembly viene archiviato all'interno di tale modulo.
assemblyFileName
può essere diverso dai nomi di tutti i moduli contenuti nell'assembly. In tal caso, il file di assembly contiene solo il manifesto dell'assembly.
Per ogni ResourceWriter oggetto ottenuto usando DefineResource, questo metodo scrive il file con estensione resources e chiama Close per chiudere il flusso.
Deve assemblyFileName
essere un nome di file semplice senza un'unità o un componente di directory. Per creare un assembly in una directory specifica, utilizzare uno dei DefineDynamicAssembly metodi che accettano un argomento della directory di destinazione.