ildanny
ildanny

Reputation: 391

c# Emit dynamic method to convert DateOnly To Datetime

I am learning IL (intermediate language) for possible applications to a C# application.

Using c#, I am trying to generate a dynamic method to convert a DateOnly into a DateTime. In C#, it would just be:

    public static DateTime ToDateTime(DateOnly dtOnly)
    {
        return dtOnly.ToDateTime(new TimeOnly(0));
    }

My code is:

using System.Reflection.Emit;

namespace ConsoleApp2
{
  public class MyModule
  {
    public static void CreateAndInvokeDynamicMethod()
    {
      var fuc = GenerateDateTimeFromDateOnly2();
      DateOnly dt = new DateOnly(1974, 1, 17);
      DateTime to = fuc.Invoke(dt);
      return;
    }

    public static Func<DateOnly, DateTime> GenerateDateTimeFromDateOnly2()
    {
      Type[] methodArgs = { typeof(int) };

      DynamicMethod methodBuilder = new DynamicMethod(
          "JustATest",
          typeof(DateTime),
          new Type[] { typeof(DateOnly) },
          typeof(MyModule).Module)
      ;

      ILGenerator ilGenerator = methodBuilder.GetILGenerator();

      // Load the DateOnly argument onto the stack
      ilGenerator.Emit(OpCodes.Ldarg_0);

      ilGenerator.Emit(OpCodes.Ldc_I4_0); // Load 0
      ilGenerator.Emit(OpCodes.Ldc_I4_0); // Load 0
      ilGenerator.Emit(OpCodes.Newobj, typeof(TimeOnly).GetConstructor(new Type[] { typeof(int), typeof(int) }));
      //Now, I have a TimeOnly in the Stack

      // Call the DateOnly.ToDateTime method
      ilGenerator.EmitCall(OpCodes.Call, typeof(DateOnly).GetMethod("ToDateTime", new Type[] { typeof(TimeOnly) }), null);
      ilGenerator.Emit(OpCodes.Ret);
      return (Func<DateOnly, DateTime>)methodBuilder.CreateDelegate(typeof(Func<DateOnly, DateTime>));
    }
  }
}

When I invoke it, I get the error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt"

Any Idea what's wrong in my code?

I also decompiled the c# into IL, but I don't see any relevant difference.

.method public hidebysig 
    instance valuetype [System.Runtime]System.DateTime ToDateTime (
        valuetype [System.Runtime]System.DateOnly dtOn
    ) cil managed 
{
    // Method begins at RVA 0x206c
    // Code size 20 (0x14)
    .maxstack 3
    .locals init (
        [0] valuetype [System.Runtime]System.DateTime
    )

    IL_0000: nop
    IL_0001: ldarga.s dtOn
    IL_0003: ldc.i4.0
    IL_0004: ldc.i4.0
    IL_0005: newobj instance void [System.Runtime]System.TimeOnly::.ctor(int32, int32)
    IL_000a: call instance valuetype [System.Runtime]System.DateTime [System.Runtime]System.DateOnly::ToDateTime(valuetype [System.Runtime]System.TimeOnly)
    IL_000f: stloc.0
    IL_0010: br.s IL_0012

    IL_0012: ldloc.0
    IL_0013: ret
} // end of method GenericClass::ToDateTime

Actually, I don't understand the need of an additional DateTime. Also, what's the purpose of an unconditional branch

    IL_000f: stloc.0
    IL_0010: br.s IL_0012
    IL_0012: ldloc.0

Upvotes: 0

Views: 267

Answers (0)

Related Questions