使用Reflection来复制struct和class之间的等效属性

时间:2014-01-01 11:54:41

标签: c# reflection

我正在制作游戏(请参阅http://haighshroom.blogspot.com了解上下文)并使用XML文件保存/加载游戏。它目前使用不同的结构作为每个类的保存格式,但继续更新保存文件结构是令人厌倦的,所以我想尝试采用以下通用方法。

假设我有3个类,它们都继承自BaseClass:

Class1,它具有Property1,Property2(假设所有属性都是整数)

Class2,具有Property2,Property3

Class3,具有Property1,Property3

现在我的新广义SaveStruct看起来像这样:

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

在保存/加载特定实体时,我想实现以下Pseudocode(两个函数都是从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);
}

我不知道如何定义的部分是:

-Exists(e.Property1) - 这需要使用Reflection来确定实例e是否定义了Property1(我们从BaseClass调用它,所以我们不知道不使用Reflection)。

-Get(e.Property1) - 如果实例e存在属性1,我们需要获取其值

-Set(e.Property1 = es.Property1) - 如果属性1确实存在于实例e中,我们需要设置其值

非常感谢。

2 个答案:

答案 0 :(得分:3)

您可以尝试使用此代码

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);
    }
}

答案 1 :(得分:2)

所有这一切的起点是System.Type类。您可以使用e.GetType()为您的类型获取此类的实例。

要查找字段,请使用GetField。如果返回null,则该字段根本不存在。

如果它返回一个值(类型为FieldInfo),则使用GetValue获取值,并使用SetValue进行设置。

反射速度相对较慢,因此如果需要考虑性能,请提前使用System.Type.getType(name)抓取System.Type对象并获取FieldInfo个对象。您不需要该类的实际实例来执行这两个操作中的任何一个,但显然您需要它来获取和设置字段值。