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,您将从中受益。
我写了一个方法:
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,您将从中受益。