簡體   English   中英

在IIS中訪問WCF單例

[英]Accessing the WCF singleton in IIS

我有一個具有instanceContextMode = single的服務(稱為MainService )。

我也有另一種服務,這種服務必須跟上述服務的單個實例( OtherService在調用函數MainService )。

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

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 getter創建對服務的虛擬調用,以便IIS將創建實例(僅當IIS尚未創建服務實例時才需要此實例)。 這顯然是一個令人費解的hack,我想知道是否有正常的方法。

我無法執行常規的單例模式,因為我托管在IIS中,並且IIS不知道如何通過某些函數(例如GetInstance )創建服務實例。

編輯1

我不希望OtherService像其他任何服務一樣與MainService進行通信,因為MainService必須將DoSomeFunction定義為服務操作,任何人都可以調用函數DoSomeFunction。 DoSomeFunction適用於OtherService,而不僅僅是任何客戶端。

只是沒有單一實例服務。 將所有狀態移到另一個類中,並使服務變為無狀態。 無狀態服務可以獲取並使用單例實例。

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

這是一個草圖:

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應用程序。 您必須假定應用程序隨時被殺死(例如,電源故障,崩潰,錯誤等)。 此外,您需要一個高可用性解決方案,該解決方案通常涉及多次實例化應用程序。

  1. 第一件事不要編寫您自己的單例代碼,因為您正在將InstanceContextMode設置為on service。 WCF將僅創建一個用於服務所有請求。

  2. 與其他服務一樣,從其他服務調用wcf服務,例如使用WCF客戶端代理。

  3. 您無需擔心IIS是否已創建實例,也可以在首次請求時創建實例。

  4. 如果您擔心從另一個服務調用主要服務的性能(如果它們在IIS中的同一應用程序的同一台計算機上),請考慮使用nettcp綁定或網絡命名管道綁定。

坦率地說,我認為您可能會遇到一些設計問題; 但是,您要問的並非不可能。

實現這個類:

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並為是否更改單例編寫邏輯,因為單例的要點是它只能實例化一次,如果您的單例管理一個狀態,那么該狀態可以更改,那么它可以具有一些主要特征。反響。

做到這一點的一種好方法是在任何客戶端代碼中保留對單例的引用並訂閱事件。 如果單例實例的地址與客戶機實例的地址不同,則客戶機代碼具有客戶機代碼保持將其改回的能力。

這將允許您對單身人士進行單元測試,但除了允許您正常運行外,還可以將其用作單身人士。

無論如何,如果您想訪問單身人士,那就很簡單:

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

我覺得這個解決方案比您目前正在做的事情要干凈得多。 但是,我仍然認為您存在設計問題,您可能需要考慮更改程序的結構。

PS / tl;博士:如果不清楚。 這是糟糕的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM