2012-01-12 16 views
0

I次のコードを持っている:このプロパティを最初にアクセスしたときにのみ作成されるようにするにはどうすればよいですか?

/// <summary> 
/// BrowserFactory responsible for deciding if you should receive a shared or isolated browser instance. 
/// </summary> 
public static class BrowserFactory 
{ 
    /// <summary> 
    /// Shared Browser Instance 
    /// </summary> 
    private static SharedBrowser _sharedBrowser; 

    /// <summary> 
    /// The window handle of the shared browser instance. 
    /// </summary> 
    private static string _sharedHwnd; 

    /// <summary> 
    /// The last thread id to access the shared browser. 
    /// </summary> 
    private static int _sharedThreadId; 

    static BrowserFactory() 
    { 
     Shared= new SharedBrowser(); 
    }  

    private static SharedBrowser Shared 
    { 
     get 
     { 
      var currentThreadId = GetCurrentThreadId(); 
      if (currentThreadId != _sharedThreadId) 
      { 
       _sharedBrowser = IE.AttachTo<SharedBrowser>(Find.By("hwnd", _sharedHwnd)); 
       _sharedThreadId = currentThreadId; 
      } 
      return _sharedBrowser; 
     } 
     set 
     { 
      _sharedBrowser = value; 
      _sharedHwnd = _sharedBrowser.hWnd.ToString(); 
      _sharedThreadId = GetCurrentThreadId(); 
     } 
    } 

    public static Browser GetBrowser() 
    { 
     return BrowserSettings.UseSharedBrowser ? Shared : new Browser(); 
    } 
} 

は、どのように私はそれは私が唯一のプロパティは、最初のコンストラクタではなく、アクセスされたSharedBrowserオブジェクトをインスタンス化することができますか?

私はSharedプロパティでこれを行うと考えましたが、プロパティからsetを呼び出すのは変です。

.NET 4.0レイジーオブジェクトで_sharedBrowserをラップすることも考えましたが、次にLazyでラップされたものを直接インスタンス化する方法がわかりません。これは、共有プロパティでユーザーは(再取り付け後に)取得します。

私は共有プロパティの.setロジックを.getに複製せずにこれをどうすることができないのか分かりません。

アイデア?

+0

お使いのブラウザの工場は、複数のスレッドによって使用されていますか? – insipid

+0

@insipidは、MSTestテストメソッドで使用されます。これらのメソッドは、性質上、異なるスレッドから実行されます。 – KingNestor

答えて

0

静的なコンストラクタの素晴らしい点は、アプリケーションごとに1回だけ呼び出されることです。後でそのような保証はありません。だから静的なコンストラクタを追加して、インスタンス化をLazy < T>に入れて、その中でLazyの.Valueを参照してください。

+0

私の.setのどこでそのレイジープロパティの値を設定する必要がありますか? – KingNestor

0

プライベートクラスレベルのSharedBrowser変数を保存し、getブロック。次に、追加の初期化ロジックを完成させるために、別のメソッドにリファクタリングしてgetsetの両方から呼び出します。

private static SharedBrowser _shared = null; 

private static SharedBrowser Shared 
{ 
    get 
    { 
     if(_shared == null) 
     { 
      _shared = new SharedBrowser(); 
      InitSharedBrowser(); 
     } 

     // the rest of your code here. 
    } 
    set 
    { 
      _shared = value; 
      InitSharedBrowser(); 
    } 
} 

private static void InitSharedBrowser() 
{ 
    // your SharedBrowser Initialization logic goes here. 
} 
+0

あなたが見ると、私の共有のセットには、ブラウザを割り当てるときに必要なことがあります。私は現在のスレッドID、ウィンドウhwndなどを記録する必要があります 私は基本的に奇妙な私の.getから私の.setを呼び出す必要があります。 – KingNestor

+0

そのロジックを別のメソッド(または可能であれば 'SharedBrowser'のコンストラクタ)にリファクタリングし、getメソッドとsetメソッドからそのメソッドを呼び出します。 –

+0

私の答えを更新して、私の言いたいことを示しました。 –

1

あなたは、静的のためだけでなく、インスタンスメンバーのために、このパターンを使用することができます。

private SomeType _myProperty; 
public SomeType MyProperty 
{ 
    get 
    { 
     if (_myProperty == null) { 
      _myProperty = new SomeType(); 
     } 
     return _myProperty; 
    } 
} 

これは怠惰なインスタンス化と呼ばれています。


EDIT:

private static SharedBrowser _shared; 
public static SharedBrowser Shared { 
    get 
    { 
     var currentThreadId = GetCurrentThreadId();   
     if _shared == null) { 
      _shared = new SharedBrowser(); 
      _sharedHwnd = _sharedBrowser.hWnd.ToString(); 
      _sharedThreadId = currentThreadId;   
     } 
     if (currentThreadId != _sharedThreadId) {   
      _sharedBrowser = IE.AttachTo<SharedBrowser>(Find.By("hwnd", _sharedHwnd));   
      _sharedThreadId = currentThreadId;   
     }   
     return _shared; 
    } 
} 
+0

私はMyProperties .setのログをその.getに複製する必要がありますか?私の例を見ると、新しい値(レコードスレッドID、ウィンドウhwndなど)を設定するときに必要ないくつかのことがあります。 – KingNestor

+0

getterに共有ブラウザを作成するので、セッターは必要ありません。コンストラクタではなく、 'if(_sharedBrowser == null)sharedBrowser = new SharedBrowser();'です。 –

+0

あなたは私のポイントを見ていません。私の財産のセッターを見てください。私は、基礎となるプロパティ_sharedBrowserが設定されているときに何かをしなければなりません。私は私のコードを複製することなく、SharedBrowser()を新しくすることはできません。 – KingNestor

関連する問題