C#创建子类的另一个实例 - Reflection?

时间:2012-12-12 15:10:18

标签: c# reflection

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

我有一个基类: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 个答案:

答案 0 :(得分:6)

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

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

abstract RoomObject Clone();

现在在Bed中实现此方法以返回new Bed(...),并在Table中返回new Table(...)。传递BedTable的构造函数所需的任何参数,以复制当前对象中的内容。

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

答案 1 :(得分:1)

这是关于反射的最好的事情之一:能够在没有客户端代码知道它的类型的情况下创建对象。有时它可能会变得混乱,甚至有时会使代码变慢,但是 - 如果使用得当 - 将使您的代码更易于管理。

例如,请查看the Factory Pattern,以及如何实施with Reflectionhere as well

答案 2 :(得分: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 */
    }
}

答案 3 :(得分:1)

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

由于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想要的人的库,就应该做反射。