jeudi 5 décembre 2019

Initialise existing anonymous object type, via reflection

I'd like to manipulate some anonymous types, by inspecting property values, and replacing specific values with a new value in certain circumstances. The problem is, anonymous type properties are read only, i.e. they don't have a setter.

My plan is to treat the anonymous types like any other immutable object, and implement a visitor pattern to return a new instance where necessary, with new property values where required.

What I need to make this work, is a way to initialise a new instance of an anonymous type, dynamically, and set the property values.

Is there a way to dynamically call the initializer for a specific object type, via reflection?

Here's some code to give you an idea of what I'm doing...

var newResults = results.Select(r => VisitResult(r));

// recursive function that visits each property of our results, and manipulates the data
// as required
object VisitResult(object result)
{
    // if the object is of our specific data type, we need to check if we need to replace it
    if (result is IDataRow row)
    {
        // check if we should replace the value, and return the new value if we have one
        return updatedValues.Lookup(row) ?? row;
    }
    else
    {
        // this doesn't work for anonymous types, as the properties are read only
        // I'd like to declare a new instance of the same anonymous type, and use 
        // the initialiser, so I can assign new values to the anonymous type properties
        foreach (var propertyInfo in result.GetType().GetProperties())
        {
            // visit the value of each property
            propertyInfo.SetValue(row, VisitResult(propertyInfo.GetValue(row)));
        }
    }
}

If I cannot achieve this via reflection, I will use Expression trees instead, I was just curious if there was a way of using initialisers via reflection, as my Google-fu hasn't managed to turn up anything relevant.





Aucun commentaire:

Enregistrer un commentaire