Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Reflection to copy across equivalent properties between struct and class

Tags:

c#

reflection

I'm making a game (see http://haighshroom.blogspot.com for context) and saving/loading the game using an XML file. It currently uses a different struct for the save format of each class, but continuing to update the save file structure is proving tiresome so I want to try and adopt the following generalised method.

Let's assume I have 3 classes, which all inherit from BaseClass:

Class1, which has Property1, Property2 (let's say all properties are ints)

Class2, which has Property2, Property3

Class3, which has Property1, Property3

Now my new generalised SaveStruct would look like this:

public struct EntityStruct
{
    public string ClassName;
    public int Property1;
    public int Property2;
    public int Property3;
    public EntityStruct()
    {
        ClassName = "";
        Property1 = Property2 = Property3 = 0;
    }
}

When saving/loading a particular entity, I want to achieve the following Pseudocode (both functions called from BaseClass):

public EntityStruct GetSaveStruct()
{
    EntityStruct es = new EntityStruct();
    es.ClassName = this.GetType().Name;
    if Exists(this.Property1) es.Property1 = Get(this.Property1);
    if Exists(this.Property2) es.Property2 = Get(this.Property2);
    if Exists(this.Property3) es.Property3 = Get(this.Property3);
}
public void LoadFromStruct(EntityStruct es)
{
    BaseClass e = (BaseClass)(Activator.CreateInstance(null, GV.NameSpace + es.ClassName).Unwrap());
    if Exists(e.Property1) Set(e.Property1 = es.Property1);
    if Exists(e.Property2) Set(e.Property2 = es.Property2);
    if Exists(e.Property3) Set(e.Property3 = es.Property3);
}

The parts I don't know how to define are:

-Exists(e.Property1) - this needs to use Reflection to determine whether the instance e has Property1 defined (we are calling this from BaseClass so we don't know without using Reflection).

-Get(e.Property1) - if Property 1 does exist for an instance e, we need to get its value

-Set(e.Property1 = es.Property1) - if Property 1 does exist from an instance e, we need to set its value

Many thanks.

like image 397
Haighstrom Avatar asked Dec 03 '25 22:12

Haighstrom


1 Answers

you can try use this code

public void ShallowCopyValues<T1, T2>(T1 firstObject, T2 secondObject)
{
    const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
    var firstFieldDefinitions = firstObject.GetType().GetFields(bindingFlags);
    IEnumerable<FieldInfo> secondFieldDefinitions =     secondObject.GetType().GetFields(bindingFlags);

    foreach (var fieldDefinition in firstFieldDefinitions)
    {
        var matchingFieldDefinition = secondFieldDefinitions.FirstOrDefault(fd => fd.Name == fieldDefinition.Name &&
                                                                                  fd.FieldType == fieldDefinition.FieldType);
    if (matchingFieldDefinition == null)
        continue;

        var value = fieldDefinition.GetValue(firstObject);
        matchingFieldDefinition.SetValue(secondObject, value);
    }
}
like image 143
Yanshof Avatar answered Dec 06 '25 15:12

Yanshof