基本クラスがあります
public class A
{
public string s1;
public string s2;
}
派生クラスもあります:
public class B : A
{
public string s3;
}
私のプログラムがクラスAのインスタンスを作成したとしましょう。
A aClassInstance = new A();
いくつかのパラメータが設定されました:
aClassInstance.s1 = "string 1";
aClassInstance.s2 = "string 2";
この時点で、クラスBのインスタンスを作成したいと思います。しかし、クラスAのインスタンスの値をBにすでに持たせたいと思います。
これDID動作しません:
public B bClassInstance = new B():
bClassInstance = (B)aClassInstance;
どちらもDIDこれ:
クラスA内にクローンメソッドを作成しました。
public B cloneA() {
A a = new A();
a = (A)this.MemberwiseClone()
return(B)a;
}
VSコードは上記の両方を取ります-しかし、実行時エラーが発生します
助けてください
あなたが持っている基本的な問題は、タイプB
のインスタンスを構築しなければならないということです(これにはタイプA
のプロパティが含まれています)。 A
インスタンスを複製するアプローチは機能しません。これは、タイプA
のインスタンスが得られ、B
に変換できないためです。
タイプAのパラメーターを受け取るクラスAおよびBのコンストラクターを作成します。クラスBのコンストラクターは、値を基本クラスAに渡すだけです。クラスAのコンストラクターは、フィールドを自分自身にコピーする方法を知っています。
class A {
public A(A copyMe) {
s1 = copyMe.s1;
...
}
class B : A {
public B(A aInstance) : base(aInstance) {
}
}
このように使用します。
A a = new A();
a.s1 = "...";
B b = new B(a);
[〜#〜]編集[〜#〜]
新しいフィールドや小道具を追加するときにA
のコンストラクターを変更する必要がない場合は、リフレクションを使用してプロパティをコピーできます。カスタム属性を使用してコピーするものを装飾するか、A
のすべての小道具/フィールドのみをコピーします。
public A (A copyMe) {
Type t = copyMe.GetType();
foreach (FieldInfo fieldInf in t.GetFields())
{
fieldInf.SetValue(this, fieldInf.GetValue(copyMe));
}
foreach (PropertyInfo propInf in t.GetProperties())
{
propInf.SetValue(this, propInf.GetValue(copyMe));
}
}
私はコードを試したことがありませんが、要点は明らかになるはずです。
クラスAで汎用クローンメソッドを作成できます。
public T Clone<T>() where T : A, new() {
return new T() { a = this.a, b = this.b};
}
または、クローンを拡張可能にしたい場合:
public T Clone<T>() where T : A, new() {
var result = new T();
this.CopyTo(result);
return result;
}
protected virtual void CopyTo(A other) {
other.a = this.a;
other.b = this.b;
}
あなたはそれをこのように使います:
A a = new A();
// do stuff with a
// Create a B based on A:
B b = a.Clone<B>();
注意:この例では、新しいA()とMemberwiseCloneの両方がタイプAの新しいオブジェクトを作成します。
自分でcopyメソッドをコーディングしたくない場合は、 AutoMapper のようなツールを見ることができます。
遊んで、私が見ることができるすべてを読んだ後、GvSとJanによる上記のソリューションの両方が機能します。しかし、私が達成したかった最終結果は、Copyメソッドで各メンバーを強制的に書き出すことではありません。
理由:a)クラスが編集され、別のオブジェクトが追加された場合、copyメソッドを更新する必要があります。他の誰かがクラスを更新すると、これを忘れる可能性があります。
b)メンバーが多く、割り当てに時間がかかる場合があります。
c)それはただ正しく「感じ」ません。 (おそらく私はとても怠け者だからです)。
幸いなことに、同じ考えを持っているのは私だけではありません。 ValueInjectorを介して非常に簡単な解決策を見つけました。 (これらのボードで多く議論されています)。
Dllを取得した後(http://valueinjecter.codeplex.com/documentation)
コードは次のようになります。
A a = new A();
a.s1 = "...";
B b = new B();
b.InjectFrom(a);
それでおしまい :)
明らかに、以下を含める必要があります。
using Omu.ValueInjecter;
そして、それを参照に追加することを忘れないでください。
たとえば、JSONシリアライザーを使用することもできます。子クラスに静的メソッドを追加すると、次のように呼び出すことができます。
var porsche = Porsche.FromCar(basicCar);
ここで、「ポルシェ」は子クラス、「車」は基本クラスです。この場合、関数は次のようになります。
public class Porsche : Car
{
public static Porsche FromCar(Car basicCar)
{
// Create a JSON string that represents the base class and its current values.
var serializedCar = JsonConvert.SerializeObject(basicCar);
// Deserialize that base class string into the child class.
return JsonConvert.DeserializeObject<Porsche>(serializedCar);
}
// Other properties and functions of the class...
}
ここでの秘訣は、子で使用できるがベースでは使用できないプロパティはデフォルト値で作成されるため、プロパティのタイプに応じて、通常はnullになることです。デシリアライズもプロパティの名前で行われるため、すべてのプロパティがコピーされます。
このコードはテストしていませんが、以前に1、2回テストしたので、機能するはずです。それが誰かを助けることを願っています。