简体   繁体   English

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

[英]C# creating another instance of subclass - Reflection?

I'm reposting a question I've just asked, but want to re-ask this question in a more concise way as I think I was causing some confusion. 我正在重新发布一个我刚刚问过的问题,但是由于我认为我造成了一些混乱,所以想以一种更简洁的方式重新提出这个问题。

I have a base class: RoomObject. 我有一个基类:RoomObject。 I have two subclasses: Bed and Table, which inherit from RoomObject. 我有两个子类:Bed和Table,它们从RoomObject继承。

I have a variable currentObject, which is of type RoomObject, but will actually hold either an instance of Bed or Table (RoomObject is never instantiated itself). 我有一个变量currentObject,它的类型为RoomObject,但实际上将保存Bed或Table的一个实例(RoomObject本身不会实例化)。

How can I clone my currentObject, without knowing its full type? 如何在不知道其完整类型的情况下克隆我的currentObject?

ie if currentObject is a Bed, I want to clone the Bed using 即如果currentObject是一张床,我想使用

currentObject = new Bed(currentObject); 

and if currentObject is a Table, I want to use 如果currentObject是一个Table,我想使用

currentObject = new Table(currentObject);

I could use reflection, by calling Activator.CreateInstance(currentObject.GetType()), and then copy across any attributes I need, but this seems messy. 我可以通过调用Activator.CreateInstance(currentObject.GetType())使用反射,然后在需要的所有属性之间进行复制,但这似乎很麻烦。

You should use the pattern known as the virtual constructor , or a cloning method . 您应该使用称为虚拟构造函数的模式或克隆方法

Add a virtual method to RoomObject that returns a copy of the current object: RoomObject添加一个虚拟方法,该方法返回当前对象的副本:

abstract RoomObject Clone();

Now implement this method in Bed to return new Bed(...) , and in the Table to return new Table(...) . 现在,在Bed实现此方法以返回new Bed(...) ,在Table实现此方法以返回new Table(...) Pass whatever parameters necessary to the constructors of Bed and Table to copy what's in the current object. 将必要的任何参数传递给BedTable的构造函数,以复制当前对象中的内容。

.NET has an interface ICloneable that is commonly used to implement this pattern. .NET具有通常用于实现此模式的ICloneable接口。 A small disadvantage of that approach is that Clone must return object , not RoomObject , so if you need RoomObject , you'd need to cast it. 这种方法的一个小缺点是Clone必须返回object而不是RoomObject ,因此,如果需要RoomObject ,则需要RoomObject转换它。

This is one of the best things about reflection: The ability to create an object without your client code knowing what type it is. 这是关于反射的最好的事情之一:能够在不让客户代码知道对象是什么类型的情况下创建对象的能力。 Sometimes it can get messy, or even slow down the code at times, but--if used correctly--will make your code a lot more manageable. 有时它可能会变得凌乱,甚至有时会使代码变慢,但是-如果使用得当,它将使您的代码更易于管理。

For example, take a look at the Factory Pattern , and how one can implement it with Reflection and here as well 例如,看一看Factory Pattern ,以及如何使用Reflection以及在这里实现

I think one solution would be implement ICloneable interface for all your objects. 我认为一种解决方案是为所有对象实现ICloneable接口。 Here's some sample code: 这是一些示例代码:

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

Instead of that, implement the ICloneable interface that's out-of-the-box on .NET Framework as others said in their answers. 取而代之的是,像其他人在回答中所说的那样,在.NET Framework上实现现成的ICloneable接口。

Since ICloneable.Clone() method returns object , what about a custom ICloneable<T> that also implements ICloneable ? 由于ICloneable.Clone()方法返回object ,那么还实现ICloneable的自定义ICloneable<T>呢?

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();
     }
}

Later, in your code... 稍后,在您的代码中...

MyCloneableObject some = new MyCloneableObject();

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

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

Implementing both built-in and custom interface is a good idea, as your cloneable will operate with other libraries that may accept ICloneable implementations. 同时实现内置接口和自定义接口是一个好主意,因为您的可克隆对象将与可能接受ICloneable实现的其他库一起运行。

Finally, rather than using reflection, this case should be solved in design-time. 最后,应该在设计时解决这种情况,而不是使用反射。 I would argue that doing with reflection should be done if you can't modify the library containing the ICloneable wannabe. 我认为如果您不能修改包含ICloneable wannabe的库,就应该进行反射。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM