C# Language
ILGenerator
खोज…
एक डायनामिकएसहॉर्म बनाता है जिसमें एक UnixTimestamp सहायक विधि होती है
यह उदाहरण कोड उत्पन्न करके ILGenerator के उपयोग को दर्शाता है जो पहले से मौजूद और नए बनाए गए सदस्यों के साथ-साथ बुनियादी अपवाद हैंडलिंग का उपयोग करता है। निम्नलिखित कोड एक डायनामिकएज़वेयर का उत्सर्जन करता है जिसमें इस c # कोड के बराबर होता है:
public static class UnixTimeHelper
{
private readonly static DateTime EpochTime = new DateTime(1970, 1, 1);
public static int UnixTimestamp(DateTime input)
{
int totalSeconds;
try
{
totalSeconds = checked((int)input.Subtract(UnixTimeHelper.EpochTime).TotalSeconds);
}
catch (OverflowException overflowException)
{
throw new InvalidOperationException("It's to late for an Int32 timestamp.", overflowException);
}
return totalSeconds;
}
}
//Get the required methods
var dateTimeCtor = typeof (DateTime)
.GetConstructor(new[] {typeof (int), typeof (int), typeof (int)});
var dateTimeSubstract = typeof (DateTime)
.GetMethod(nameof(DateTime.Subtract), new[] {typeof (DateTime)});
var timeSpanSecondsGetter = typeof (TimeSpan)
.GetProperty(nameof(TimeSpan.TotalSeconds)).GetGetMethod();
var invalidOperationCtor = typeof (InvalidOperationException)
.GetConstructor(new[] {typeof (string), typeof (Exception)});
if (dateTimeCtor == null || dateTimeSubstract == null ||
timeSpanSecondsGetter == null || invalidOperationCtor == null)
{
throw new Exception("Could not find a required Method, can not create Assembly.");
}
//Setup the required members
var an = new AssemblyName("UnixTimeAsm");
var dynAsm = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
var dynMod = dynAsm.DefineDynamicModule(an.Name, an.Name + ".dll");
var dynType = dynMod.DefineType("UnixTimeHelper",
TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public);
var epochTimeField = dynType.DefineField("EpochStartTime", typeof (DateTime),
FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly);
var cctor =
dynType.DefineConstructor(
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName | MethodAttributes.Static, CallingConventions.Standard,
Type.EmptyTypes);
var cctorGen = cctor.GetILGenerator();
cctorGen.Emit(OpCodes.Ldc_I4, 1970); //Load the DateTime constructor arguments onto the stack
cctorGen.Emit(OpCodes.Ldc_I4_1);
cctorGen.Emit(OpCodes.Ldc_I4_1);
cctorGen.Emit(OpCodes.Newobj, dateTimeCtor); //Call the constructor
cctorGen.Emit(OpCodes.Stsfld, epochTimeField); //Store the object in the static field
cctorGen.Emit(OpCodes.Ret);
var unixTimestampMethod = dynType.DefineMethod("UnixTimestamp",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
CallingConventions.Standard, typeof (int), new[] {typeof (DateTime)});
unixTimestampMethod.DefineParameter(1, ParameterAttributes.None, "input");
var methodGen = unixTimestampMethod.GetILGenerator();
methodGen.DeclareLocal(typeof (TimeSpan));
methodGen.DeclareLocal(typeof (int));
methodGen.DeclareLocal(typeof (OverflowException));
methodGen.BeginExceptionBlock(); //Begin the try block
methodGen.Emit(OpCodes.Ldarga_S, (byte) 0); //To call a method on a struct we need to load the address of it
methodGen.Emit(OpCodes.Ldsfld, epochTimeField);
//Load the object of the static field we created as argument for the following call
methodGen.Emit(OpCodes.Call, dateTimeSubstract); //Call the substract method on the input DateTime
methodGen.Emit(OpCodes.Stloc_0); //Store the resulting TimeSpan in a local
methodGen.Emit(OpCodes.Ldloca_S, (byte) 0); //Load the locals address to call a method on it
methodGen.Emit(OpCodes.Call, timeSpanSecondsGetter); //Call the TotalSeconds Get method on the TimeSpan
methodGen.Emit(OpCodes.Conv_Ovf_I4); //Convert the result to Int32; throws an exception on overflow
methodGen.Emit(OpCodes.Stloc_1); //store the result for returning later
//The leave instruction to jump behind the catch block will be automatically emitted
methodGen.BeginCatchBlock(typeof (OverflowException)); //Begin the catch block
//When we are here, an OverflowException was thrown, that is now on the stack
methodGen.Emit(OpCodes.Stloc_2); //Store the exception in a local.
methodGen.Emit(OpCodes.Ldstr, "It's to late for an Int32 timestamp.");
//Load our error message onto the stack
methodGen.Emit(OpCodes.Ldloc_2); //Load the exception again
methodGen.Emit(OpCodes.Newobj, invalidOperationCtor);
//Create an InvalidOperationException with our message and inner Exception
methodGen.Emit(OpCodes.Throw); //Throw the created exception
methodGen.EndExceptionBlock(); //End the catch block
//When we are here, everything is fine
methodGen.Emit(OpCodes.Ldloc_1); //Load the result value
methodGen.Emit(OpCodes.Ret); //Return it
dynType.CreateType();
dynAsm.Save(an.Name + ".dll");
विधि ओवरराइड बनाएँ
यह उदाहरण दिखाता है कि जनरेट की गई कक्षा में ToString
पद्धति को ओवरराइड कैसे किया जाए
// create an Assembly and new type
var name = new AssemblyName("MethodOverriding");
var dynAsm = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
var dynModule = dynAsm.DefineDynamicModule(name.Name, $"{name.Name}.dll");
var typeBuilder = dynModule.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class);
// define a new method
var toStr = typeBuilder.DefineMethod(
"ToString", // name
MethodAttributes.Public | MethodAttributes.Virtual, // modifiers
typeof(string), // return type
Type.EmptyTypes); // argument types
var ilGen = toStr.GetILGenerator();
ilGen.Emit(OpCodes.Ldstr, "Hello, world!");
ilGen.Emit(OpCodes.Ret);
// set this method as override of object.ToString
typeBuilder.DefineMethodOverride(toStr, typeof(object).GetMethod("ToString"));
var type = typeBuilder.CreateType();
// now test it:
var instance = Activator.CreateInstance(type);
Console.WriteLine(instance.ToString());
Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow