C# 简化并可能概括了我的对象克隆方法

C# simplify and perhaps generalize my object cloning method

我写了一个方法:

class CopyableFloatCommand : FloatCommand
{
    public CopyableFloatCommand DeepCopy(LocationHeaderDTO locHeader, string commandId,
        List<FloatProductDetailsDTO> recountProuducts)
    {
        var newCommand = (CopyableFloatCommand)MemberwiseClone();
        newCommand.Location = locHeader ?? newCommand.Location;
        newCommand.CommandId = commandId ?? newCommand.CommandId;
        newCommand.RecountProducts = recountProuducts ?? newCommand.RecountProducts;
        return newCommand;
    }
}

然后通过以下方式调用它:

_tCheckinCommand = _pTCommand.DeepCopy(stagingLocHeadDto, SCICommand,
    new List<FloatProductDetailsDTO>(_pTCommand.MoveProducts));

为了深度复制 FloatCommand 类型的对象。

由于 MemberwiseClone() 是一种受保护的方法,因此必须按照您在上面看到的方式调用它 - 不能在方法参数中解析 FloatCommand 类型并通过 fc.MemberwiseClone() 调用它,因为例子。由于我的方法应该适用于 FloatCommand 类型,因此我创建了一个新的嵌套 class CopyableFloatCommand,它继承自 FloatCommand。 DeepCopy 方法然后浅克隆 FloatCommand,转换为子类型并更改一些属性 as/when 需要。

专门为此目的创建一个新的 class 似乎有点笨拙,当时我没有看到更明显的编写方式。就代码行而言,是否有更简单的方法来使用上述深度复制?如果另一个 class,UserCommand 试图深度复制一个 User 对象怎么办? UserComand 将是 FloatCommand 的兄弟,因此它们都继承自 Command。该方法将针对不同的类型解析不同的参数(尽管我可以完全删除参数并在需要时使用实例变量),因为不同的子类型具有略微不同的属性。

鉴于此,是否有更通用的方法来编写 DeepCopy 方法,以供所有命令类型访问,以避免某些代码重复,给定上述限制?

谢谢!

我认为您怀疑克隆对象和在克隆后改变其状态的责任应该分开 - 因为您再次面临类似的任务(我的意思是 UserCommand)。

在这种情况下我会做以下事情:

创建变异界面:

public interface ICopyCommandMutation
{
  void Mutate(Command target); 
}

为了可扩展性,我将创建默认的 muate 实现:

public class NoMutation : ICopyCommandMutation
{
  public void Mutate(Command target) {}
}

创建 CopyableCommand class 并将 DeepCopy() 方法移到那里(您还应该从 CopyableCommand 继承 FloatCommand):

public CopyableCommand : Command 
{
   public CopyableCommand DeepCopy(ICopyCommandMutation commandMutation = null)
   {
      var newCommand = (CopyableCommand)MemberwiseClone();
      if (commandMutation == null) commandMutation = new NoMutation();
      commandMutation.Mutate(newCommand);
      return newCommand;
   }
}

现在所有 CopyableCommand 继承者都可以用 'mutations' 复制 - 你只需要实现 class。例如,您问题中的 FloatCommand 'mutations':

public class ChangeLocationRecountProducts : ICopyCommandMutation
{
  // these fields should be initialized some way (constructor or getter/setters - you decide
  LocationHeaderDTO locHeader;
  string commandId;
  List<FloatProductDetailsDTO> recountProducts;

  public void Mutate(Command floatCommand)
  {
     var fc = floatCommand as FloatCommand;
     if (fc == null) { /* handle problems here */ }
     fc.Location = locHeader ?? fc.Location;
     fc.CommandId = commandId ?? fc.CommandId;
     fc.RecountProducts = recountProuducts ?? fc.RecountProducts;
  }
}

用法如下:

var clrp = new ChangeLocationRecountProducts();
// ... setting up clrp
_tCheckinCommand = _pTCommand.DeepCopy(clrp);

现在,如果您需要 'mutate' UserCommand - 您可以对其进行单独的修改 class 并将修改逻辑保留在那里。在不同的突变中进行不同突变的能力(只需定义单独的突变 classes)是免费的。 我在这里看到的唯一问题是您可能无法创建 CopyableCommand 并从中继承其他命令(第 3 方库?)。解决方案是使用 Castle 动态代理。

我没有使用过 Automapper,但我怀疑它在做类似的事情。

解决方案不是 'lines-of-code optimal' - 但如果您在复制实例时必须改变大量命令 classes,您将从中受益。