【问题标题】:Copying All Class Fields and Properties To Another Class将所有类字段和属性复制到另一个类
【发布时间】:2017-07-04 20:23:36
【问题描述】:

我有一个通常包含字段、属性的类。我想要实现的不是这个:

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
  • 我希望该方法复制值而不是创建新对象。 [只是模仿我在示例中所述的行为]
  • 我希望函数是递归的 [如果该类包含另一个类,它也会将其值复制到最内部的类]
  • 除非我允许,否则不要复制 null 或空值。
  • 复制所有字段、属性甚至事件。

【问题讨论】:

  • 要复制字段,您必须使用字段集合 item.GetType().GetFields()
  • @VMA:你能提供一个答案吗?我也不希望它是递归的,所以它对每个孩子都做同样的事情。
  • @VMA:我很抱歉,但你能再看一下笔记吗,我更新了它们以满足我的所有要求。如果你能帮忙,请因为我过去 3 天都在尝试,但没有运气,
  • 对不起,我不明白。您想要“复制值而不是创建新对象的方法”,同时想要“递归函数”。如果你将一个对象复制到另一个类,这意味着你传递了它的引用,所有的字段都是一样的。
  • 我想将所有东西作为对目的地的参考,就好像你只是在做object1 = object2

标签: c#


【解决方案1】:

基于 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);

【讨论】:

  • 它是递归的,也不会复制空值或空值?
  • 我希望方法检查属性是否是一个类,然后对它做同样的事情。
  • @RuneS:如果您尝试进行“深度复制”,您会发现自己陷入了痛苦的世界。你将如何处理循环引用?收藏类型?延迟/惰性评估和可枚举?如果这种事情有直接的答案,它已经被实现为框架方法。
  • @Aaronaught :在我的情况下,集合和枚举不必被深度复制。
  • @RuneS:这与您提出的要求不一致,并建议您需要花更多时间思考。如果您不深复制集合,那么您也不会深复制集合中的任何元素in,这意味着您将对(可能)确切的对象使用不一致的规则同类型。无论如何,您的问题在此之前已经被问过很多次了。
【解决方案2】:

您可以使用序列化来序列化对象 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    相关资源
    最近更新 更多