vendredi 22 décembre 2017

Cannot set a struct property using reflection due to boxing issues

In my code I have the interface

public interface MyInterface
{
    object Value { get; set; }
}

which is supposed to be a base interface for a few structs, e.g. a struct like this:

public struct DemoStruct : MyInterface
{
    public object Value { get; set; }
}

and I want to be able to set the Value property using Reflection. But due to issues with boxing and unboxing, I cannot set the property directly nor have define a setting method on the interface which can be called later (see examples below), so I have to resort to this working solution, but I would rather not want to program against the implementation (i.e. setting the field name explicitly, as shown below):

public struct MyStruct : MyInterface
{
    internal object ValueField; // Workaround.

    public object Value
    { 
        get { return this.ValueField; }
        set { this.ValueField = value; } 
    } 
}

The setting method:

public void SetValue<TStruct>(TStruct instance) where TStruct : struct, IMyInterface
{
    (instance as IMyInterface).GetType().GetField("ValueField", BindingFlags.Instance | BindingFlags.NonPublic).SetValueDirect(__makeref(instance), this.GetSomeValue());
    //                                            ^^^^^^^^^^^^
}    

Below are two alternatives I came up with, which sadly don't work due to boxing / unboxing issues I guess:

(instance as IMyInterface).GetType().GetProperty(nameof(IMyInterface.Value), BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, this.GetSomeValue());
//                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
// I would prefer this, because it does not depend on the implementation, but does not work due to the boxing.

(instance as IMyInterface).SetValue(this.GetSomeValue());
// Implied that IMyInterface provides a method definition of SetValue, this would be the shortest and cleanest solution, but it does not work either.


I glady appreciate any help.





Aucun commentaire:

Enregistrer un commentaire