0

我正在重新发布我刚刚提出的一个问题,但我想以更简洁的方式重新提出这个问题,因为我认为我造成了一些混乱。

我有一个基类:RoomObject。我有两个子类:Bed 和 Table,它们继承自 RoomObject。

我有一个变量 currentObject,它是 RoomObject 类型,但实际上将保存 Bed 或 Table 的实例(RoomObject 本身永远不会实例化)。

如何在不知道其完整类型的情况下克隆我的 currentObject?

即如果 currentObject 是床,我想克隆床使用

currentObject = new Bed(currentObject); 

如果 currentObject 是一个表,我想使用

currentObject = new Table(currentObject);

我可以通过调用 Activator.CreateInstance(currentObject.GetType()) 来使用反射,然后复制我需要的任何属性,但这看起来很混乱。

4

4 回答 4

6

您应该使用称为虚拟构造函数的模式或克隆方法

添加一个返回当前对象副本的虚拟方法RoomObject

abstract RoomObject Clone();

现在在Bedto returnnew Bed(...)Tableto return 中实现这个方法new Table(...)。将任何必要的参数传递给构造函数BedTable复制当前对象中的内容。

.NET 有一个ICloneable通常用于实现此模式的接口。这种方法的一个小缺点是Clone必须返回object,而不是RoomObject,所以如果你需要RoomObject,你需要强制转换它。

于 2012-12-12T15:14:41.147 回答
1

ICloneable正如其他人在回答中所说的那样,在 .NET Framework 上实现开箱即用的接口,而不是那样做。

既然ICloneable.Clone()方法返回object,那么自定义ICloneable<T>也实现了ICloneable呢?

public interface ICloneable<T> : ICloneable
    where T : class
{
    T TypedClone();
}

public class MyCloneableObject : ICloneable<MyCloneableObject>
{
     public string Some { get; set; }

     public object Clone()
     {
         MyCloneableObject clone = new MyCloneableObject { Some = this.Some };
     }

     public MyCloneableObject TypedClone()
     {
          return (MyCloneableObject)Clone();
     }
}

稍后,在您的代码中...

MyCloneableObject some = new MyCloneableObject();

if(some is ICloneable<MyCloneableObject>)
{
    MyCloneableObject myClone = some.TypedClone();

    // .. or the standard `Clone()`:
    myClone = (MyCloneableObject)some.Clone();
}

实现内置和自定义接口是一个好主意,因为您的可克隆将与可能接受ICloneable实现的其他库一起运行。

最后,这种情况应该在设计时解决,而不是使用反射。我会争辩说,如果你不能修改包含想要的库,那么应该进行反射ICloneable

于 2012-12-12T15:33:14.410 回答
1

我认为一种解决方案是为所有对象实现 ICloneable 接口。这是一些示例代码:

class RoomObject : ICloneable
{
    public abstract object Clone();
}

class Bed : ICloneable
{
    public override object Clone()
    {
        return new Bed();
    }
}

class Table : ICloneable
{
    public override object Clone()
    {
        return new Table();
    }
}

class Program
{
    public static void Main(String[] args)
    {
        RoomObject ro = /* from some other places*/
        RoomObject newOne = ro.Clone() as RoomObject;  /* here's what you what */
    }
}
于 2012-12-12T15:20:59.727 回答
1

这是关于反射的最好的事情之一:在客户端代码不知道它是什么类型的情况下创建对象的能力。有时它会变得混乱,甚至有时会减慢代码的速度,但是——如果使用得当——会让你的代码更易于管理。

例如,看看Factory Pattern,以及如何使用 Reflection来实现它,以及这里

于 2012-12-12T15:16:59.903 回答