Section 157.1: Creates a DynamicAssembly that contains a UnixTimestamphelpermethod
ThisexampleshowstheusageoftheILGeneratorbygeneratingcodethatmakesuseofalreadyexistingandnew createdmembersaswellasbasicExceptionhandling.ThefollowingcodeemitsaDynamicAssemblythatcontains an equivalent to this c# code:
publicstaticclassUnixTimeHelper
{
privatereadonlystaticDateTimeEpochTime=newDateTime(1970,1,1);
publicstaticintUnixTimestamp(DateTimeinput)
{
inttotalSeconds; try
{
totalSeconds=checked((int)input.Subtract(UnixTimeHelper.EpochTime).TotalSeconds);
}
catch(OverflowExceptionoverflowException)
{
thrownewInvalidOperationException(“It’stolateforanInt32timestamp.”,overflowException);
}
returntotalSeconds;
}
}
//Gettherequiredmethods
vardateTimeCtor=typeof(DateTime)
.GetConstructor(new[]{typeof(int),typeof(int),typeof(int)});
vardateTimeSubstract=typeof(DateTime)
.GetMethod(nameof(DateTime.Subtract),new[]{typeof(DateTime)}); vartimeSpanSecondsGetter=typeof(TimeSpan)
.GetProperty(nameof(TimeSpan.TotalSeconds)).GetGetMethod(); varinvalidOperationCtor=typeof(InvalidOperationException)
.GetConstructor(new[]{typeof(string),typeof(Exception)});
if(dateTimeCtor==null||dateTimeSubstract==null|| timeSpanSecondsGetter==null||invalidOperationCtor==null)
{
thrownewException(“CouldnotfindarequiredMethod,cannotcreateAssembly.”);
}
//Setuptherequiredmembers
varan=newAssemblyName(“UnixTimeAsm”);
vardynAsm=AppDomain.CurrentDomain.DefineDynamicAssembly(an,AssemblyBuilderAccess.RunAndSave); vardynMod=dynAsm.DefineDynamicModule(an.Name,an.Name+”.dll”);
vardynType=dynMod.DefineType(“UnixTimeHelper”,
TypeAttributes.Abstract|TypeAttributes.Sealed|TypeAttributes.Public);
varepochTimeField=dynType.DefineField(“EpochStartTime”,typeof(DateTime), FieldAttributes.Private|FieldAttributes.Static|FieldAttributes.InitOnly);
varcctor=
dynType.DefineConstructor(
MethodAttributes.Private|MethodAttributes.HideBySig|MethodAttributes.SpecialName| MethodAttributes.RTSpecialName|MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
varcctorGen=cctor.GetILGenerator();
cctorGen.Emit(OpCodes.Ldc_I4,1970);//LoadtheDateTimeconstructorargumentsontothestack
cctorGen.Emit(OpCodes.Ldc_I4_1);
cctorGen.Emit(OpCodes.Ldc_I4_1);
cctorGen.Emit(OpCodes.Newobj,dateTimeCtor);//Calltheconstructor cctorGen.Emit(OpCodes.Stsfld,epochTimeField);//StoretheobjectinthestaticfieldcctorGen.Emit(OpCodes.Ret);
varunixTimestampMethod=dynType.DefineMethod(“UnixTimestamp”, MethodAttributes.Public|MethodAttributes.HideBySig|MethodAttributes.Static, CallingConventions.Standard,typeof(int),new[]{typeof(DateTime)});
unixTimestampMethod.DefineParameter(1,ParameterAttributes.None,”input”);
varmethodGen=unixTimestampMethod.GetILGenerator();
methodGen.DeclareLocal(typeof(TimeSpan));
methodGen.DeclareLocal(typeof(int));
methodGen.DeclareLocal(typeof(OverflowException));
methodGen.BeginExceptionBlock();//Beginthetryblock
methodGen.Emit(OpCodes.Ldarga_S,(byte)0);//Tocallamethodonastructweneedtoloadthe addressof it
methodGen.Emit(OpCodes.Ldsfld,epochTimeField);
//Loadtheobjectofthestaticfieldwecreatedasargumentforthefollowingcall methodGen.Emit(OpCodes.Call,dateTimeSubstract);//CallthesubstractmethodontheinputDateTime methodGen.Emit(OpCodes.Stloc_0);//StoretheresultingTimeSpaninalocal methodGen.Emit(OpCodes.Ldloca_S,(byte)0);//Loadthelocalsaddresstocallamethodon it methodGen.Emit(OpCodes.Call,timeSpanSecondsGetter);//CalltheTotalSecondsGetmethodontheTimeSpan
methodGen.Emit(OpCodes.Conv_Ovf_I4);//ConverttheresulttoInt32;throwsanexceptiononoverflow
methodGen.Emit(OpCodes.Stloc_1);//storetheresultforreturninglater
//Theleaveinstructiontojumpbehindthecatchblockwillbeautomaticallyemitted
methodGen.BeginCatchBlock(typeof(OverflowException));//Beginthecatchblock
//Whenwearehere,anOverflowExceptionwasthrown,thatisnowonthestack methodGen.Emit(OpCodes.Stloc_2);//Storetheexceptioninalocal. methodGen.Emit(OpCodes.Ldstr,”It’stolateforanInt32timestamp.”);
//Loadourerrormessageontothestack
methodGen.Emit(OpCodes.Ldloc_2);//Loadtheexceptionagain methodGen.Emit(OpCodes.Newobj,invalidOperationCtor);
//CreateanInvalidOperationExceptionwithourmessageandinnerException methodGen.Emit(OpCodes.Throw);//Throwthecreatedexception methodGen.EndExceptionBlock();//Endthecatchblock
//Whenwearehere,everythingisfine
methodGen.Emit(OpCodes.Ldloc_1);//Loadtheresultvalue
methodGen.Emit(OpCodes.Ret);//Return it
dynType.CreateType();
dynAsm.Save(an.Name+”.dll”);
Section157.2:Createmethodoverride
ThisexampleshowshowtooverrideToStringmethodingeneratedclass
//createanAssemblyandnewtype
varname=newAssemblyName(“MethodOverriding”);
vardynAsm=AppDomain.CurrentDomain.DefineDynamicAssembly(name,AssemblyBuilderAccess.RunAndSave);
vardynModule=dynAsm.DefineDynamicModule(name.Name,$”{name.Name}.dll”);
vartypeBuilder=dynModule.DefineType(“MyClass”,TypeAttributes.Public|TypeAttributes.Class);
//defineanewmethod
vartoStr=typeBuilder.DefineMethod(
“ToString”,//name
MethodAttributes.Public|MethodAttributes.Virtual,//modifiers
typeof(string),//returntype
Type.EmptyTypes);//argumenttypes
varilGen=toStr.GetILGenerator();
ilGen.Emit(OpCodes.Ldstr,”Hello,world!”);
ilGen.Emit(OpCodes.Ret);
//setthismethodasoverrideofobject.ToString typeBuilder.DefineMethodOverride(toStr,typeof(object).GetMethod(“ToString”)); vartype=typeBuilder.CreateType();
//nowtestit:
varinstance=Activator.CreateInstance(type);
Console.WriteLine(instance.ToString());
About us and this blog
We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.
Request a free quote
We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.
Subscribe to our newsletter!
More from our blog
See all postsRecent Posts
- Chapter161:ImportGoogleContacts 30/06/2024
- Chapter160:IncludingFontResources 29/06/2024
- Chapter159:CreatingOwnMessageBoxin WindowsFormApplication 28/06/2024