将所有类字段和属性复制到另一个类

时间:2014-02-14 02:06:58

标签: c#

我有一个通常包含Fields,Properties的类。我想要实现的不是这个:

class Example
{
    public string Field = "EN";
    public string Name { get; set; }
    public int? Age { get; set; }
    public List<string> A_State_of_String { get; set; }
}

public static void Test()
{
    var c1 = new Example
    {
        Name = "Philip",
        Age = null,
        A_State_of_String = new List<string>
        {
            "Some Strings"
        }
    };
    var c2 = new Example();

    //Instead of doing that
    c2.Name = string.IsNullOrEmpty(c1.Name) ? "" : c1.Name;
    c2.Age = c1.Age ?? 0;
    c2.A_State_of_String = c1.A_State_of_String ?? new List<string>();

    //Just do that
    c1.CopyEmAll(c2);
}

我想出了什么,但没有按预期工作。

public static void CopyEmAll(this object src, object dest)
{
    if (src == null) {
        throw new ArgumentNullException("src");
    }

    foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(src)) {
        var val = item.GetValue(src);
        if (val == null) {
            continue;
        }
        item.SetValue(dest, val);
    }
}

问题:

  • 虽然我检查了null,但似乎绕过了它。
  • 似乎没有复制字段。

注意:

  • 我不想将AutoMapper用于解决某些技术问题。
  • 我想要方法复制值而不是创建新对象。 [只是模仿我在例子中陈述的行为]
  • 我希望函数是递归的[如果类包含另一个类,它将其值复制到最内层的那个]
  • 除非我允许,否则不要复制空值或空值。
  • 复制所有字段,属性甚至事件。

2 个答案:

答案 0 :(得分:5)

根据Leo的回答,但使用 Generics 并复制字段:

public void CopyAll<T>(T source, T target)
{
    var type = typeof(T);
    foreach (var sourceProperty in type.GetProperties())
    {
        var targetProperty = type.GetProperty(sourceProperty.Name);
        targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
    }
    foreach (var sourceField in type.GetFields())
    {
        var targetField = type.GetField(sourceField.Name);
        targetField.SetValue(target, sourceField.GetValue(source));
    }       
}

然后只是:

CopyAll(f1, f2);

答案 1 :(得分:0)

您可以使用序列化来序列化对象A并反序列化为对象B - 如果它们具有非常相同的结构,您可以在此处查看对象深层复制。 Deep cloning objects

我知道您不想使用Automapper,但如果类型只有SIMILAR结构,您应该使用基于反射的Automapper。你可以下载一个nuget并在这里找到一些信息: https://www.nuget.org/packages/AutoMapper/

您的代码将如下所示

public TOutput CopyAll<TInput, TOutput>(TInput input)
{
    var config = new MapperConfiguration(cfg => cfg.CreateMap<TInput, TOutput>());
    IMapper mapper = config.CreateMapper();
    return mapper.Map<TOutput>(vstup);
}