繁体   English   中英

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类型上工作,我创建了一个新的嵌套类CopyableFloatCommand,它继承自FloatCommand。 DeepCopy方法然后浅层克隆FloatCommand,强制转换为子类型并在需要时更改某些属性。

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

鉴于上述约束,有一种更通用的编写DeepCopy方法的方法,可供所有Command类型访问以避免某些代码重复?

谢谢!

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

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

创建变异接口:

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

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

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

创建CopyableCommand类并在那里移动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继承者都可以使用'mutation'进行复制 - 您只需要实现该类。 例如,你问题中的FloatCommand'突变':

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

现在,如果你需要'改变'UserCommand - 你可以为它做单独的变异类并保持变异逻辑。 能够在不同的情况下进行不同的突变(仅通过定义单独的突变类)是免费的。 我能在这里看到的唯一问题是你可能无法创建CopyableCommand并从中继承其他命令(第三方库?)。 解决方案是使用Castle动态代理。

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

解决方案不是“代码行最优” - 但如果在复制实例时必须改变大量命令类,则可以从中受益。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM