C#创建子类反射的另一个实例?

C#创建子类反射的另一个实例?,c#,reflection,C#,Reflection,我正在转载一个我刚刚问过的问题,但我想用一种更简洁的方式重新问这个问题,因为我认为我造成了一些混乱 我有一个基类:RoomObject。 我有两个子类:Bed和Table,它们继承自RoomObject 我有一个变量currentObject,它的类型是RoomObject,但实际上会保存Bed或Table的实例(RoomObject本身从未实例化) 在不知道其完整类型的情况下,如何克隆currentObject i、 e.如果currentObject是一张床,我想使用 currentObje

我正在转载一个我刚刚问过的问题,但我想用一种更简洁的方式重新问这个问题,因为我认为我造成了一些混乱

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

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

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

i、 e.如果currentObject是一张床,我想使用

currentObject = new Bed(currentObject); 
如果currentObject是一个表,我想使用

currentObject = new Table(currentObject);

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

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

将虚拟方法添加到
RoomObject
,该方法返回当前对象的副本:

abstract RoomObject Clone();
现在在
Bed
中执行此方法以返回
新床(…)
,并在
表中执行此方法以返回
新表(…)
。将任何必要的参数传递给
Bed
Table
的构造函数,以复制当前对象中的内容


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

这是反射的一个优点:在客户端代码不知道对象类型的情况下创建对象的能力。有时它会变得混乱,甚至有时会减慢代码的速度,但如果使用正确,会使代码更易于管理


例如,看看如何实现它,我认为一个解决方案是为所有对象实现IClonable接口。下面是一些示例代码:

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 */
    }
}

相反,在.NETFramework上实现开箱即用的接口,正如其他人在回答中所说的那样

既然
ICloneable.Clone()
方法返回
object
,那么同样实现
ICloneable
的自定义
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();
     }
}
公共接口ICloneable:ICloneable
T:在哪里上课
{
T型克隆();
}
公共类MyCloneableObject:可克隆
{
公共字符串Some{get;set;}
公共对象克隆()
{
MyCloneableObject克隆=新的MyCloneableObject{Some=this.Some};
}
公共MyCloneableObject类型克隆()
{
返回(MyCloneableObject)克隆();
}
}
稍后,在您的代码中

MyCloneableObject some = new MyCloneableObject();

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

    // .. or the standard `Clone()`:
    myClone = (MyCloneableObject)some.Clone();
}
MyCloneableObject some=新的MyCloneableObject();
如果(有些是可克隆的)
{
MyCloneableObject myClone=some.TypedClone();
//..或标准的“克隆()”:
myClone=(MyCloneableObject)some.Clone();
}
实现内置接口和自定义接口是一个好主意,因为您的cloneable将与其他可能接受
IClonable
实现的库一起运行


最后,这种情况应该在设计时解决,而不是使用反射。我认为,如果您不能修改包含
ICloneable
wannabe的库,就应该使用反射。

那么
ICloneable
呢?这是做这些事情的内置接口。啊,好的!是的,这很有道理。谢谢,并为双重问题的帖子表示歉意。@MatíasFidemraizer返回
object
而不是
RoomObject
@MatíasFidemraizer这是一个很好的注释,非常感谢!我在答案中添加了
ICloneable
。谢谢@嘿,你喜欢讨论<代码>对象
但毕竟
房间对象
。如果您不喜欢
ICloneable
,只需制作另一个同样实现
ICloneable
的接口,就像
ICloneable
。。。但是返回
object
并不意味着OP最终不能强制转换到
RoomObject
。顺便说一句,我不知道为什么在你们讨论所有事情时,我会和你们讨论这个问题……根据工厂的不同,有一个更好的选择:通用约束<代码>其中T:new()允许您调用泛型类型构造函数而无需反射。好的,您提供了一些示例。。。但这不是和dasblinkenlight one相同的答案吗…?嗯,我们在同一时间发布。两个答案基本上基于相同的原则,但正如您所说,我有示例代码。:)