如何使用反射来更改缺少setter的属性?

时间:2016-05-12 11:36:57

标签: c# .net reflection getter

我有两个只有属性getter的类

public class A 
{
    public A(string name) 
    {
        Name = name;
    }
    public string Name { get; }
    public string Value { get; set;}
    public string Data { get; set;}
}

public class B
{
    public B(string name) 
    {
        Name = name;
    }
    public string Name { get; }
    public string Value { get; set;}
}

它们的形状不同,但共享一些相同的属性名称和类型。 如果只有吸气剂,我该如何复制价值?

这是我将对象作为构造函数参数发送以从新对象中提取值时的典型情况。然后我需要逐个复制值。这会产生大量代码,难以维护。

这可以变得更简单吗?当目标只有getter属性时,有没有办法使用反射来复制对象?

1 个答案:

答案 0 :(得分:0)

可以创建一个辅助函数来复制目标对象只有属性getter的两个对象。

试试这个;

public static void CopyItem<U, T>(U source, T target)
{
    // Need a way to rename the backing-field name to the property Name ("<A>k__BackingField" => "A")
    Func<string, string> renameBackingField = key => new string(key.Skip(1).Take(key.IndexOf('>') - 1).ToArray());

    // Get public source properties (change BindingFlags if you need to copy private memebers as well)
    var sourceProperties = source.GetType().GetProperties().ToDictionary(item => item.Name);
    // Get "missing" property setter's backing field
    var targetFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField).ToDictionary(item => renameBackingField(item.Name));

    // Copy properties where target name matches the source property name
    foreach(var sourceProperty in sourceProperties)
    {
        if (targetFields.ContainsKey(sourceProperty.Key) == false)
            continue; // No match. skip

        var sourceValue = sourceProperty.Value.GetValue(source);
        targetFields[sourceProperty.Key].SetValue(target, sourceValue);
    }
}

这是一般性描述。在复制值以防止异常之前,您可能还需要检查属性和字段数据类型。名称和数据类型都应匹配。

使用CopyItem在构造函数中复制匹配的源属性;

public class SomeClass
{
    public SomeClass(SomeSourceClass source)
    {
        Helper.CopyItem(source, this);
    }
}