簡體   English   中英

引用Windows Service的WCF調用

[英]WCF call that references Windows Service

我有一項長期服務,可以從一個來源獲取數據,對其進行處理,然后將其存儲在數據庫中,等等。

我想向其他應用程序公開該服務的某些方法。 目前,我們是通過.NET Remoting完成此操作的,但我想轉到WCF。

不幸的是,我所連接的端點永遠不會是我通過長期運行的服務所暴露的端點。 下面是一個簡單的示例:

    [ServiceContract]
    public interface ITestWcfService
    {
        [OperationContract]
        CounterResult GetCurrentValue();
    }

public class TestWcfService : ITestWcfService
    {
        private ITestWindowsService _service;
        public TestWcfService() { /*NOTE: For discoverability*/ }
        public TestWcfService(ITestWindowsService service)
        {
            _service = service;
        }

        public CounterResult GetCurrentValue()
        {
            return _service.GetCurrentValue();
        }
    }

public interface ITestWindowsService
    {
        CounterResult GetCurrentValue();
    }

然后,我得到了實際的Windows服務,該服務通過ServiceHost類自托管WCF服務。

public partial class TestWindowsService : ServiceBase, ITestWindowsService
{
    private static ServiceHost _wcfService;

    public TestWindowsService()
    {
        InitializeComponent();
    }

    public void OnStart(string[] args)
    {
        //Create instance of WCF, passing in reference to this service instance
        TestWcfService wcf = new TestWcfService(this);
        _wcfService = new ServiceHost(wcf);
    }

        public CounterResult GetCurrentValue()
    {
        //Note: Some logic here
    }
}

現在,這種或多或少的工作原理是,每次我調用TestWcfServiceClient() ,它將使用默認構造函數並創建Wcf服務的新實例,而不使用Windows服務創建的實例。 這意味着,當我調用GetCurrentValue()由於未設置_service成員,因此會得到空引用。

我到處尋找解決方案,並找到了一些引用ServiceHostFactoryServiceHostIInstanceProvider但它們似乎都非常非常復雜。

您提供的任何想法將不勝感激。

編輯 :這是我的ServiceModel信息

<system.serviceModel>
    <services>
      <service name="WcfService.TestWcfService">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfService/TestWcfService/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="" binding="basicHttpBinding" contract="WcfService.ITestWcfService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, 
          set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

WCF是非常可擴展的,但是要提供這種可擴展性,它也非常復雜。 我認為,如果要使用此實現,那就不應該了。 您必須創建一種更改服務工廠的行為,以便您可以使用自定義構造函數而不是空的構造函數。

但是,我認為可能還有另一種選擇。 由於服務和WCF共享同一個應用程序域,因此它們可以通過靜態對象共享值。

我將移動承載要公開給底層程序集(如果尚未公開)的值的邏輯,並且服務和WCF服務將看到相同的實例,因此您無需更改所有WCF管道。

您試圖將一個方形的釘子放在一個圓孔中。

WCF被明確設計為能夠獨立於其托管方式來調用業務邏輯。 您正在嘗試維護在主機層(在本例中為Window的服務)中具有業務邏輯的舊的遠程設計。 結果,您要求以一種在WCF中可能但又難看的方式將信息傳遞回主機,這通常由於許多良好的原因而被避免。

如果您想要干凈的WCF設計,則需要創建抽象層並將業務邏輯移出現有的TestWindowsService類。 然后,Windows服務創建WCF服務主機,WCF主機創建WCF服務,並且WCF服務不依賴於承載它的類。

說了這么多...

實際回答您的問題:

從概念上講,您編寫的代碼應該可以使用。 到目前為止,將對象實例傳遞到ServiceHost構造函數是避免編寫自定義IInstanceProvider的復雜性的最簡單方法。 需要檢查的幾件事:

  1. 將服務實例傳遞到ServiceHost構造函數時,需要將其標記為單例

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

  2. 確保初始化確實按照您認為的方式工作:

    1. 如果您的服務為null,則在您的TestService(ITestWindowsService)構造函數上設置一個防護措施,該防護措施將引發。
    2. 您對TestWcfService()的默認構造函數有評論,說“為了可發現性”。 我將刪除該構造函數(至少在進行故障排除時)。 一段代碼可能正在使用該構造函數來托管您不需要的服務實例。 這很可能導致您的應用開始引發異常或編譯錯誤,指出您的實際問題。

如果仍然有問題:app.config的“服務模型”部分是什么樣的?

暫無
暫無

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

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