mardi 17 mai 2022

Non-reflective way to set properties of a type known at compile time

I am working on a project that requires a user to be able to modify properties of an object within a certain list of types, known at compile time.

For example, say I have a type defined by

public class A
{
   public float foo;
}

To set properties without reflection at near-native speeds during runtime (which is necessary for the project), I used a C# script which enumerates through the properties using reflection to generate code that looks something like this, which is then compiled.

public void Set(A obj, string path, object value)
{
    switch (path)
    {
        case "foo":
            obj.foo = (float)value;
            break;
    }
}

This works fine for simple types, but for more complex types, specifically where struct properties are its members, it becomes more difficult.

public class B
{
    public C foo { get; set; }
}
public struct C
{
    public float bar;
}

The code generated by this system no longer works, because accessing the struct property creates a copy.

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            // Cannot modify the return value of 'C.bar' because it is not a variable
            obj.foo.bar = (float)value;
            break;
    }
}

Now, what I can do is modify the system to create a temporary struct variable, modify the member I want to access, and set the property's value to the temp variable, like so.

public void Set(B obj, string path, object value)
{
    switch (path)
    {
        //...
        case "foo.bar":
            C tmp = obj.foo;
            tmp.bar = (float)value;
            obj.foo = tmp;
            break;
    }
}

This system has several problems though. Nested struct properties would be hell to unwrap, and I would have to check every single parent property to ensure a setter method exists. This seems unnecessary and cumbersome, but I don't see any other option.

Is there a way that I can set property values for an object from a string path without runtime reflection?





Aucun commentaire:

Enregistrer un commentaire