vendredi 1 décembre 2017

VerificationException when setting readonly fields (C#)

I am trying to write code that can set arbitrary fields on caller-provided objects which may include anonymous ones. Creating delegates is not possible (Expression compiler realizes that anonymous objects' fields are readonly), so I chose to emit some IL. However, when doing this I am running into VerificationException ("Operation could destabilize he runtime"). The same simple code runs just fine on objects with regular fields. Fails on readonly fields. What else could be done here? I am running .Net 4.6.2.

Thanks in advance!

class TestRegular
{
    private string field;
}

class TestReadOnly
{
    private readonly string field;
}

class Program
{
    static void Main(string[] args)
    {
        Verify(new TestRegular());     // this works
        Verify(new TestReadOnly());    // this does not work
        Verify(new { field = "abc" }); // this does not work
        Console.WriteLine("Done");
    }

    private static void Verify<T>(T test)
    {
        var fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
        Action <T, object> setter = CompileSetter<T>(fields[0]);
        setter(test, "value");
    }

    private static Action<TResult, object> CompileSetter<TResult>(FieldInfo field)
    {
        string methodName = field.ReflectedType.FullName + ".TestSetter";
        DynamicMethod setterMethod = new DynamicMethod(methodName, null, new[] { typeof(TResult), typeof(object) }, true);
        ILGenerator gen = setterMethod.GetILGenerator();

        gen.Emit(OpCodes.Ldarg_0);
        gen.Emit(OpCodes.Ldarg_1);
        gen.Emit(OpCodes.Castclass, field.FieldType);
        gen.Emit(OpCodes.Stfld, field);

        gen.Emit(OpCodes.Ret);
        return (Action<TResult, object>)setterMethod.CreateDelegate(typeof(Action<TResult, object>));
    }
}





Aucun commentaire:

Enregistrer un commentaire