vendredi 29 janvier 2021

C# Reflection -Missing Fields?

I'm using reflection to create a new instance Item B from an instance of Item A. These are different objects, but share some level of commonality. In this sample case, they both inherit from a base class.

Base Class:

public abstract class Common
{
    public string Value { get; set; }
    public virtual string Ignored { get; }
}

I then have two classes that I am working with, the original class, and the output:

public class Original : Common
{
    public override string Ignored => "This will get ignored";
}

public class Output : Common { }

If I create a new instance of Original and give the Value Property a value, the I am able to see that value within one of the auto-generated backing fields. All of this using reflection, I can then use the Activator to create an instance of my Output class and am able to set the value of the Value Property

My process is to find the commonality, get all fields (properties if based on an interface) of that object, and then with the FieldInfo I can read the value from Original and set it in Output.

My problem lies with the virtual property called Ignored, the backing field doesn't have a value, but if I read directly from the propertyinfo then I can get the value.

What am I missing with my understanding of how this following line is made up?

public override string Ignored => "This will get ignored";

Is it because it is an override? Or because it uses the => way of setting the property.

If this doesn't have an underlying field, what is the best way to match already used properties so that I only find those that don't have a backing field?

This is just test code at the moment, but for reference, this is basically my method:

private object CreateObject(object original, Type commonType, Type outputType)
{
    BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

    var response = Activator.CreateInstance(outputType, nonPublic: true);
    if (commonType.IsInterface)
    {
        foreach (var info in commonType.GetProperties(flags))
        {
            object clonedValue = info.GetValue(original); //this is simplified for ease
            var method = outputType.GetProperty(info.Name)?.GetSetMethod(nonPublic: true);
            if (method != null)
                method.Invoke(response, flags, null, new object[] { clonedValue }, null);
        }
    }
    else
    {
        // ** This only gets the fields of the common type **
        //foreach (var info in commonType.GetFields(flags))
        //{
        //    object clonedValue = this.Clone(info.GetValue(original), implementations);
        //    info.SetValue(response, clonedValue);
        //}

        // ** Testing to get all fields of original type, and then its base type - based on the above commented out code
        var fields = this.GetFieldsRecursive(original.GetType(), flags);
        //var value = commonType.GetProperty("Ignored").GetValue(original); // Proves I can get the value from the original object
        foreach (var info in fields)
        {
            object clonedValue = info.GetValue(original); // this is simplified for ease
            info.SetValue(response, clonedValue);
        }
    }


    return response;
}

I hope that makes sense

Any ability to help fill some gaps in my knowledge would be massively appreciated.





Aucun commentaire:

Enregistrer un commentaire