2011-11-03 4 views
15

派生オブジェクトの作成時に特定のメソッドを自動的に呼び出せるようにしたいと思いますが、どうやってそれを行うのか考えることはできません。次のコードが示しています。もう一つの答えは、OnLoadをお勧めしますが、私はMacでUnityに対してこれをやっていて、OnLoadは私のプラットフォームでサポートされていないようです。助言がありますか?すべてのコンストラクタが実行された直後に自動的に特定のメソッドを呼び出す方法はありますか?

あなたは ABCを達成したい、ACB を達成しているあなたの例に基づいて
public class Parent { 

    public Parent() 
    { 
     // A. Stuff to do before child constructor code runs 
     DoThisAutomaticallyAfterConstruction(); 
    } 

    public void DoThisAutomaticallyAfterConstruction() 
    { 
     // C. In this example, this will run after A, before B. I want it to run ABC 
    } 
} 

public class Child : Parent { 

    public Child() : base() 
    { 
     // B. Stuff to do here after parent constructor code runs 
    } 
} 
+2

これはコードです。基本クラスは派生クラスに関係するべきではありません。また、コンストラクタはオブジェクトの初期化された状態を設定する必要があります。 – Jason

+1

+1 @ jason - 私は同意します。 – JonH

答えて

13

残念ながら、あなたが望むことを行うための組み込みの方法はありません(これは、頻繁に要求される機能です)。

回避策の1つは、コンストラクタを直接呼び出してオブジェクトを作成せず、静的メソッドを実装してオブジェクトを作成するファクトリパターンを実装することです。たとえば、次のように

public class MyClass 
{ 
    public MyClass() 
    { 
    // Don't call virtual methods here! 
    } 

    public virtual void Initialize() 
    { 
    // Do stuff -- but may be overridden by derived classes! 
    } 
} 

その後、追加します。

public static MyClass Create() 
{ 
    var result = new MyClass(); 

    // Safe to call a virtual method here 
    result.Initialize(); 

    // Now you can do any other post-constructor stuff 

    return result; 
} 

、代わりの

var test = new MyClass(); 

をやっ@Jeremyトッドさん(受け入れ)が作品にお答えしながら、あなたが

var test = MyClass.Create(); 
+0

ああ、素晴らしい!私は工場について聞いたことがありますが、これは私がそれらをもっと理解するのに役立ちます。 –

+0

@RobinKing私の編集した答えを参照して、工場パターンの詳細についてのいくつかの指針を示してください。スタティックファクトリメソッドは単純なアプローチですが、ファクトリオブジェクトを使用する方が好きな人もいれば、使用する必要がある状況もあります。 – phoog

+1

これは非常に古い投稿ですが、コンストラクタを 'private'に変更すると便利な場合があります。これはクライアントに工場を使用させることになります。 –

2

子コンストラクタの後にコードを実行するには、A(親コンストラクタ)でコードを呼び出すことができないB(子コンストラクタ)の後に呼び出しを行う必要があります。

子クラスコンストラクタの最後にDoThisAutomaticallyAfterConstruction()を移動しますか?

本当に奇妙な質問ですが。

+0

悲しいことに、開かれていないクラスでは、必ずしもそのトリックを行うわけではありません。偶数以上の派生クラスは、子コンストラクタの実行終了後にさらに初期化を行うことができるため、コンストラクタ。 –

+1

@JeremyTodd - そうであれば、私たちはOPからより多くの情報を必要とするでしょう。私はこのポストの情報に答えています。 – JonH

+0

通常のコードでは奇妙ですが、UIコードを扱う際にはこれがしばしば必要です。しかし、著者が言ったように、通常はOnLoadイベントを使用します。 –

4

これは工場の候補者のようです。すべてのコンストラクタをprivateまたはprotectedにして、コンシューマにオブジェクトのインスタンスが必要なときに、コードのコンシューマがファクトリメソッドを呼び出さなければなりません。ファクトリメソッドでは、new演算子を使用してオブジェクトを作成し、オブジェクトを返す前にDoThisAutomaticallyAfterConstruction()を呼び出します。

EDIT

工場は静的メソッドであってもよいし、あるいは、あなたは工場出荷時のオブジェクトを有することができます。例えば、Wikipediaの抽象ファクトリパターンはhttp://en.wikipedia.org/wiki/Abstract_factory_pattern、実際の実装ではADO.NET DbProviderFactoriesのドキュメントはhttp://msdn.microsoft.com/en-us/library/wda6c36e.aspxです。

+0

理にかなう。ありがとうございました! –

0

を行うことができますこの問題に対する広く受け入れられている解決策ですあなたのクラスがnewを使って正しく構築できないので、それには欠点があります。いくつかのC#機能を使用して一般的なソリューションを紹介しましょう。このソリューションでは、ファクトリパターンを使用する必要はなく、オブジェクトの作成後に何かを呼び出す必要はなく、単一のメソッドでインターフェイスを実装するだけで、どのクラスでも動作します。 まず、私たちは私たちのクラスが実装する必要がありますインターフェイスを宣言します。

public interface IInitialize { 
    void OnInitialize(); 
} 

次は、私たちは、このインターフェイスのスタティック拡張クラスを追加し、Initializeメソッドを追加します。

public static class InitializeExtensions 
{ 
    public static void Initialize<T>(this T obj) where T: IInitialize 
    { 
     if (obj.GetType() == typeof(T))  
      obj.OnInitialize(); 
    } 
} 

、私たちが必要な場合は、クラスとその子孫のすべてが、オブジェクトが完全に構築された直後にイニシャライザを呼び出す必要がある場合は、IInitializeを実装し、コンストラクタに行を追加します。

public class Parent : IInitialize 
{ 
    public virtual void OnInitialize() 
    { 
     Console.WriteLine("Parent"); 
    } 

    public Parent() 
    { 
     this.Initialize(); 
    } 
} 

public class Child : Parent 
{ 
    public Child() 
    { 
     this.Initialize(); 
    } 

    public override void OnInitialize() 
    { 
     Console.WriteLine("Child"); 
    } 
} 

public class GrandChild : Child 
{ 
    public GrandChild() 
    { 
     this.Initialize(); 
    } 

    public override void OnInitialize() 
    { 
     Console.WriteLine("GrandChild"); 
    } 
} 

派生クラスが拡張メソッドInitializeを呼び出すと、実際のクラスから行われなかった呼び出しはすべて抑制されます。

関連する問題