2014-07-13 75 views
1

我有一個instanceContextMode = single服務(稱爲MainService)。訪問IIS中的WCF單身人士

我也有另一項服務,這項服務必須與上述服務的單個實例(OtherServiceMainService中的調用函數)進行交談。

我決定做的方式是像這樣:

public class OtherService 
{ 
    ... 
    MainService.DoSomeFunction(); 
    ... 
} 

,並在MainService類:

public class MainService 
{ 
    private ManualResetEvent manualEventInCtor = new ManualResetEvent(false); 
    private static MainService _theInstance = null; 
    private static MainService TheInstance 
    { 
     get 
     { 
      if(_theInstance == null) 
      { 
       MainService.IMainContract dummyClient = new MainService.MainContractClient(); 
       dummyClient.function(); 
       manualEventInCtor.WaitOne(); 
      } 
      return _theInstance; 
     } 
     set 
     { 
      _theInstance = value; 
     } 
    } 
    ... 
    public MainService() 
    { 
     ... 
     TheInstance = this; 
     manualEventInCtor.set(); 
     ... 
    } 

    public static void DoSomeFunction() 
    { 
     TheInstance.SomeFunction(); 
    } 
    ... 
} 

我最終有TheInstance吸氣創建的僞呼叫服務,以便IIS將創建實例(只有在服務實例尚未由IIS創建時才需要)。這顯然是一個令人費解的黑客,我想知道是否有一個正常的方式。

我不能做一個正常的單身模式,因爲我在IIS中託管,IIS不知道如何從某個函數創建服務實例(例如GetInstance)。

編輯1

我不想OtherService說話像任何其他服務的MainService,因爲那時MainService必須定義DoSomeFunction作爲服務運行,而且任何人都可以調用該函數DoSomeFunction。 DoSomeFunction適用於OtherService,不適用於任何客戶端。

回答

1

只是沒有單一實例服務。將所有狀態轉移到不同的類中,並使您的服務成爲無狀態。無狀態服務可以獲取單例實例並使用它。

通過將所有有狀態移動到您自己的代碼中,您可以控制何時創建實例。你可以強制它被創建。

這裏有一個素描:

class MySingleton { 
//You can use any lazy initialization logic you like 
//I just used a static initializer as an example 
public static readonly MySingleton Instance = new ...(); 

//Move all static data into this class 
//WCF never has to instantiate this class 
//Use it from anywhere you like 
} 

class MyWcfService { 
//This WCF service has no state 
//Therefore it does not need single instance mode 
//Any instancing mode will do 
//No one except WCF will ever need to use this class 
public void SomeServiceMethod() { 
    MySingleton.Instance.DoSomething(); 
} 
} 

此無關的問題:有狀態的Web服務和Web應用程序是要避免的。您必須假定該應用程序隨時被終止(例如電源故障,崩潰,錯誤...)。另外,您需要一個高可用性解決方案,通常涉及多次實例化應用程序。如您在設置 InstanceContextMode到單論服務

+0

即使您忽視了我的具體問題,這看起來也是正確的做法。你能否詳細說明如何做到這一點?我真的不明白怎麼做。你的意思是服務中的所有函數應該是GetInstance()。Function()? – Binyamin

+0

@Binyamin我添加了一個草圖。如果這不能解決你的問題,恐怕我不明白。在這種情況下,幫助我解釋我錯過了什麼。 – usr

+0

我現在明白了,謝謝,這應該起作用。 – Binyamin

0
  1. 第一件事,不要編寫自己的單。 WCF將只創建一個 用於提供所有請求。

  2. 從其他服務調用wcf服務作爲任何其他服務,如 使用WCF客戶端代理。

  3. 你不需要打擾是IIS有 創建實例或不創建實例會在第一次請求。

  4. 如果您費心從另一個 服務調用主要服務的表現,如果他們是在IIS同一臺機器相同的應用程序, 考慮使用nettcp結合或淨命名管道綁定。

+0

我已經添加了一個編輯來解釋爲什麼這不適合我。無論如何。 – Binyamin

0

我會坦率地說,我認爲你可能有一些設計問題;然而,你所要求的並不是不可能的。

實現這個類:

public static class Singleton<T> where T : new() 
{ 
    public static event EventHandler<SingletonChangedEventArgs> SingletonChangedEvent; 
    public static T Instance { get { return instance; } } 
    private static T instance = new T(); 
    public static void SetSingleton(T newInstance) 
    { 
     T temp = instance; 
     instance = newInstance; 
     if (SingletonChangedEvent != null) 
      SingletonChangedEvent(instance, new SingletonChangedEventArgs { PreviousInstance = temp}); 
    } 
} 

而這其中還有:

public class SingletonChangedEventArgs : EventArgs 
{ 
    public object PreviousInstance { get; set; } 
} 

讓您的主要服務像任何其他服務一樣,例如:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class MyService : IMyService 
{ 
    public MyService() 
    { 
     //Pay attention to this, the rest of this class is fluff. 
     Singleton<MyService>.SetSingleton(this); 
    } 
    public String Hello(String Name) 
    { 
     return "Hello " + Name; 
    } 

    public Person GetPerson() 
    { 
     return new Person() { Age = 21 }; 
    } 
} 

我強烈建議你訂閱SingletonChangedEvent並且寫入邏輯單元是否因爲poi而改變單例的nt是它只能被實例化一次,如果你的單例管理一個狀態,那麼該狀態可以被改變,它可能會有一些重大影響。

這樣做的一個好方法是在任何客戶端代碼中保持對單例的引用並訂閱該事件。如果單例實例的地址與客戶端代碼的地址不同,客戶端代碼將保留將其更改回來的能​​力。

這將允許你單元測試你的單例,但也允許你使用它作爲單例,除了允許你正常運行它。

無論如何,如果你想訪問你的單身它很容易:

Singleton<MyService>.Instance.Hello("Aelphaeis"); 

我覺得這個解決方案比你目前在做什麼更清潔了很多;然而,我仍然認爲你有設計問題,你可能需要考慮改變你的程序結構。

PS/tl; dr:如果不明確。這是糟糕的設計。