簡體   English   中英

C#創建子類的另一個實例-反射?

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

我正在重新發布一個我剛剛問過的問題,但是由於我認為我造成了一些混亂,所以想以一種更簡潔的方式重新提出這個問題。

我有一個基類:RoomObject。 我有兩個子類:Bed和Table,它們從RoomObject繼承。

我有一個變量currentObject,它的類型為RoomObject,但實際上將保存Bed或Table的一個實例(RoomObject本身不會實例化)。

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

即如果currentObject是一張床,我想使用

currentObject = new Bed(currentObject); 

如果currentObject是一個Table,我想使用

currentObject = new Table(currentObject);

我可以通過調用Activator.CreateInstance(currentObject.GetType())使用反射,然后在需要的所有屬性之間進行復制,但這似乎很麻煩。

您應該使用稱為虛擬構造函數的模式或克隆方法

RoomObject添加一個虛擬方法,該方法返回當前對象的副本:

abstract RoomObject Clone();

現在,在Bed實現此方法以返回new Bed(...) ,在Table實現此方法以返回new Table(...) 將必要的任何參數傳遞給BedTable的構造函數,以復制當前對象中的內容。

.NET具有通常用於實現此模式的ICloneable接口。 這種方法的一個小缺點是Clone必須返回object而不是RoomObject ,因此,如果需要RoomObject ,則需要RoomObject轉換它。

這是關於反射的最好的事情之一:能夠在不讓客戶代碼知道對象是什么類型的情況下創建對象的能力。 有時它可能會變得凌亂,甚至有時會使代碼變慢,但是-如果使用得當,它將使您的代碼更易於管理。

例如,看一看Factory Pattern ,以及如何使用Reflection以及在這里實現

我認為一種解決方案是為所有對象實現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 */
    }
}

取而代之的是,像其他人在回答中所說的那樣,在.NET Framework上實現現成的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();
     }
}

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

MyCloneableObject some = new MyCloneableObject();

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

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

同時實現內置接口和自定義接口是一個好主意,因為您的可克隆對象將與可能接受ICloneable實現的其他庫一起運行。

最后,應該在設計時解決這種情況,而不是使用反射。 我認為如果您不能修改包含ICloneable wannabe的庫,就應該進行反射。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM