2010-11-21 14 views
2

なしで可能性のある派生オブジェクトを追加する方法がありますかベースオブジェクトまたは派生オブジェクトのインスタンスを独自に作成できるようにしますか?私はそれがほぼ矛盾していると考えています。私が思い付くことができていた唯一の方法について派生子クラスのコレクション

はこのような子供の基本実装から親コレクションに追加することです。

// Child constructors 
private void Child() { } 
protected void Child(Parent parent) 
{ 
    parent.Collection.Add(this); 
} 

これは、常にでインスタンス化される子オブジェクトを強制的に親であるが、親コレクションに子クラスを追加するのはむしろ面倒な実装のようである子供から。私はメソッドにType型の変数を渡すことができ、これは行く方法かもしれませんが、渡された型に作成/キャストする方法がわかりません。


アップデート:私は場合には、これは誰もが私が何をしたいのより良い絵を与え、可能な汎用的なChildCollection.Add方法として、このようなコードで遊んだ...我々はそれかどうかを確認します

// Currently testing directly in Parent class; 
// can later be moved/modified for Parent's ChildCollection class. 
public Child AddTest(string info, Type derivedType) 
{ 
    ConstructorInfo ci = derivedType.GetConstructor(new Type[] { typeof(Parent) }); 
    Child myBaby = (Child) ci.Invoke(new Object[] { this }); 
    myBaby.Initialize(info); 
    return myBaby; 
} 

これは、その後のようなコードで呼び出すことができます:あなたが親タイプのインスタンスを作成できるようにする必要がないことについて深刻だった場合は、単にその作り、

Child newChild = Parent.AddTest("Hello World", typeof(DerivedChild)); 
+0

パブリックコンストラクタではなく、抽象基本クラス、派生型、およびファクトリメソッドが必要ですか?しかし、なぜ? –

+0

親クラスとの関連付けを強制するには、親なしでは存在できず、セットアップ中に特定のコールチェーンに従うので、オーバーライド可能なメソッドをそのコンストラクタの基本クラスから呼び出すべきではないからです。 – RobinHood70

+0

PSでは、基本クラスは抽象クラスではありません。そのメソッドのいくつかのオーバーライドを可能にする本格的な実装です。 – RobinHood70

答えて

1

最終的に、私は私の更新で投稿したものと非常によく似たコードになりました。私はそれを一般的なオブジェクトファクトリまたは制限されたオブジェクトファクトリ(この場合、Childクラスから派生したものに限る)のいずれかにとって有用なテクニックだと思うので、ここに投稿しています。

基本的な考え方は、カスタムコレクションを作成し、Addメソッドを使用してオブジェクトをインスタンス化し、Child派生のオーバーライドされた初期化を適切に処理することです。ここで

は私がなってしまったコードのスケルトンです:

// Use standard Child 
public Child Add(string initInfo) 
{ 
    Child newChild = new Child(this.Parent); 
    // There's actually a bit more coding before Initialize() 
    // in the real thing, but nothing relevant to the example. 
    newChild.Initialize(initInfo); 
    List.Add(newChild); 
    return newChild; 
} 

// Overload for derived Child. 
public Child Add(Type childDerivative, string initInfo) 
{ 
    if (!childDerivative.IsSubclassOf(typeof(Child))) 
     throw new ArgumentException("Not a subclass of Child."); 
    ConstructorInfo ci = childDerivative.GetConstructor(
     BindingFlags.Instance | 
     BindingFlags.Public | BindingFlags.NonPublic | 
     BindingFlags.FlattenHierarchy | 
     BindingFlags.ExactBinding, 
     null, new Type[] { typeof(Parent) }, null); 
    if (ci == null) 
     throw new InvalidOperationException("Failed to find proper constructor."); 
    newChild = (Child)ci.Invoke(new Object[] { this.Parent }); 
    newChild.Initialize(initInfo); 
    List.Add(newChild); 
    return newChild; 
} 

これは、すべての可能な派生子供をカバーしないかもしれないので、彼らが自分のパラメータを追加している場合は特に、クライアントアプリケーションは、(作成することができますコンストラクタ)、私はおそらくまた、ユーザーが標準の "新しい子(親)"でChildオブジェクトをインスタンス化している場合には、Add(Child child)メソッドも提供すると思いますすべての標準的な初期化ステップを期待どおりに実行します。

0

長期的に作品コンストラクタ保護者はそれを抽象的に宣言するか宣言する。

サブクラスインスタンスを作成してリストに簡単に追加すると、ベースクラスのインスタンスを作成できなくなります。

+0

その部分はすでに、プライベートおよびプロテクトされたコンストラクタと共に上に示されています。問題は、親オブジェクトに子クラスを作成して、クライアントアプリケーションが自分のChildクラスから派生している可能性があり、基本インスタンスではなく派生インスタンスを追加したい場合に、コレクションに追加することです。 – RobinHood70

1

制限があるのは、子オブジェクトが親なしで存在してはならないということです。 "IsAttached"や "Parent"のようなプロパティを公開し、内部メソッドを使用して子オブジェクトを親に接続する方法はありますか?次に、子オブジェクトはコードベースのどこにでも構築できますが、接続するまでは有効な子オブジェクトにはなりません。

- internal Attach(parent) 
- internal Detach() 
- public IsAttached 

親コレクションは、子オブジェクトを追加していくつかの検証を実行するメソッドを実装できます。フォームとコントロールのラインに沿って考えています。

Collection.Add(child) 
{ 
    // throw error if the child is not the right type 
    child.Attach(this) 
    base.add(child)  
} 
+0

私のアップデートに記載されている方法に慣れてきましたが(私は一瞬で完全なコードを投稿します)、これも便利な方法です。私のアプローチが問題になってしまうと、私はこのようなものを実装するかもしれません。 – RobinHood70