2011-01-27 18 views
4

タイプBの新しいオブジェクトをタイプAの既存のオブジェクトから作成したいと思います.BはAから継承しています。オブジェクトのすべてのプロパティ値タイプAはタイプBのオブジェクトにコピーされます。これを達成するための最良の方法は何ですか?継承と継承階層をキャストする

class A 
{ 
    public int Foo{get; set;} 
    public int Bar{get; set;} 
} 

class B : A 
{ 
    public int Hello{get; set;} 
} 


class MyApp{ 
    public A getA(){ 
     return new A(){ Foo = 1, Bar = 3 }; 
    } 

    public B getB(){ 
     A myA = getA(); 
     B myB = myA as B; //invalid, but this would be a very easy way to copy over the property values! 
     myB.Hello = 5; 
     return myB; 
    } 

    public B getBAlternative(){ 
     A myA = getA(); 
     B myB = new B(); 

     //copy over myA's property values to myB 
     //is there a better way of doing the below, as it could get very tiresome for large numbers of properties 
     myB.Foo = myA.Foo; 
     myB.Bar = myA.Bar; 

     myB.Hello = 5; 
     return myB; 
    } 
} 

答えて

4
class A { 
    public int Foo { get; set; } 
    public int Bar { get; set; } 

    public A() { } 

    public A(A a) { 
     Foo = a.Foo; 
     Bar = a.Bar; 
    } 
} 

class B : A { 
    public int Hello { get; set; } 

    public B() 
     : base() { 

    } 

    public B(A a) 
     : base(a) { 

    } 
} 

EDIT

をしたくない場合各プロパティをコピーするには、AとBをシリアライズ可能にしてインスタンスをシリアライズします。 f A(ストリームであり、ファイルではない)とそれを使ってBのインスタンスを初期化します。しかし、私はあなたに警告し、これが嫌で、オーバーヘッドのかなりを持っています

A a = new A() { 
    Bar = 1, 
    Foo = 3 
}; 

System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(A)); 
System.IO.Stream s = new System.IO.MemoryStream(); 
xs.Serialize(s, a); 

string serial = System.Text.ASCIIEncoding.ASCII.GetString(ReadToEnd(s)); 
serial = serial.Replace("<A xmlns", "<B xmlns"); 
serial = serial.Replace("</A>", "</B>"); 

s.SetLength(0); 
byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(serial); 
s.Write(bytes, 0, bytes.Length); 
s.Position = 0; 

xs = new System.Xml.Serialization.XmlSerializer(typeof(B)); 
B b = xs.Deserialize(s) as B; 

あなたはReadToEndhereに関する詳細な情報を得ることができます。

+0

+1 - 私はコンストラクターのアプローチも好むでしょう。 – nulltoken

+0

シリアライザコードを追加していただきありがとうございます。おそらく、すべてのメンバーをループして値をコピーするためにリフレクションを使用することもできますが、それにはオーバーヘッドが多くなります。 –

0

これはOOメカニズムでは不可能ですが、AutoMapperは、この非常に使用するために作成されています。

3

あなたはBのための明示的なキャスト演算子を定義できますので、あなたが行うことができます

public static explicit operator B(A a) 
    { 
    B b = new B(); 
    b.Foo = a.Foo; 
    b.Bar = a.Bar; 
    b.Hello = 5; 
    return b; 
    } 

を:

B myB = (B)myA; 
+0

これはコードの良いリファクタリングです - 私はBがAからのキャストを担当するのが好きです。タイプAのオブジェクトを受け入れたBのコンストラクタを作成することもできます。残念ながら、各プロパティは交互になります。 –

+0

キャスト演算子をオーバーライドする必要はありません... – bitxwise

+0

あるクラスからサブクラスに移動すると、新しいメモリ割り当てが必要なため、実装には各値をコピーする必要があります。 +1を与えましたが、私はこれも他の開発者にとっては難しいと思っています。個人的には、ベースクラスを取得するためにオーバーロードされたコンストラクタを提供します。 – Rob

関連する問題