vendredi 28 juillet 2017

Cannot set certain type values via IL Emit on Object

I'm creating a function using ILGenerator and Emit to set the value of a property on a specified instance. The main reasons for this being the performance aspects to the solution I'm working on. I have a basic form of code which should take 2 objects and load them via IL to invoke a set function. The problem I am finding is the value I'm passing to be set seems to be ignored and another seemingly generated value is set in its place.

This is the basic usage example made in LinqPad I have created to demonstrate this problem:

void Main()
{
    var instance = new TestClass
    {
        Id = new Guid("f0564ce7-f249-4105-8fc4-2c65cfe095f6"),
        StringValue = "Something",
        IntValue = 0
    };

    MethodOne(instance);
}

private void MethodOne(TestClass instance)
{
    var setStringMethod = GenerateMethodAssignment("StringValue");
    setStringMethod(instance, "Something Else");

    var setGuidMethod = GenerateMethodAssignment("Id");
    setGuidMethod(instance, new Guid("f8b0fae2-40bb-422a-815f-2300cceb4329"));

    var setIntMethod = GenerateMethodAssignment("IntValue");
    setIntMethod(instance, 100);
    instance.Dump();
}

// Define other methods and classes here
public class TestClass
{
    public Guid Id { get; set; }
    public string StringValue { get; set; }
    public int IntValue { get; set; }
}

private Action<object, object> GenerateMethodAssignment(string propName)
{
    var setMethod = typeof(TestClass).GetProperty(propName).GetSetMethod();
    var argTypes = new Type[] { typeof(object), typeof(object) };
    var method = new DynamicMethod(Guid.NewGuid().ToString(), null, argTypes, GetType(), true);

    var ilGenerator = method.GetILGenerator();
    ilGenerator.Emit(OpCodes.Ldarg_0);
    ilGenerator.Emit(OpCodes.Ldarg_1);
    ilGenerator.Emit(OpCodes.Call, setMethod);
    ilGenerator.Emit(OpCodes.Ret);

    var action = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
    return action;
}

Output: Value set on object

The string value is set fine but a Guid or Integer value is not set as I would expect. I am fairly new to IL and may be having too high expectations here for the code to be this simple.

However even so I noticed running this code multiple times seems to generate the values for IntValue and Id in a seemingly sequential order so I curious where exactly these values are coming from.





Aucun commentaire:

Enregistrer un commentaire