C#创建子类反射的另一个实例?
我正在转载一个我刚刚问过的问题,但我想用一种更简洁的方式重新问这个问题,因为我认为我造成了一些混乱 我有一个基类:RoomObject。 我有两个子类:Bed和Table,它们继承自RoomObject 我有一个变量currentObject,它的类型是RoomObject,但实际上会保存Bed或Table的实例(RoomObject本身从未实例化) 在不知道其完整类型的情况下,如何克隆currentObject i、 e.如果currentObject是一张床,我想使用C#创建子类反射的另一个实例?,c#,reflection,C#,Reflection,我正在转载一个我刚刚问过的问题,但我想用一种更简洁的方式重新问这个问题,因为我认为我造成了一些混乱 我有一个基类:RoomObject。 我有两个子类:Bed和Table,它们继承自RoomObject 我有一个变量currentObject,它的类型是RoomObject,但实际上会保存Bed或Table的实例(RoomObject本身从未实例化) 在不知道其完整类型的情况下,如何克隆currentObject i、 e.如果currentObject是一张床,我想使用 currentObje
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相同的答案吗…?嗯,我们在同一时间发布。两个答案基本上基于相同的原则,但正如您所说,我有示例代码。:)