2013-01-23 54 views
0

我有一個長期運行的服務,從一個源獲取數據,操縱它,把它存儲在數據庫中,等調用WCF引用Windows服務

我想暴露於該服務的一些方法其他應用。目前我們通過.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> 

回答

0

WCF是非常可擴展的,但爲了提供這種可擴展性也很複雜。在我看來,如果你想使用這種實現方式,那麼應該是這樣。你必須創建一個改變服務工廠的行爲,以便你可以使用自定義構造函數而不是空的構造函數。

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

我會移動你想要暴露的值到底層程序集的邏輯(如果你還沒有),並且服務和WCF服務都會看到相同的實例,所以你不需要全部改變WCF管道。

+0

是的,我想我要解決的問題是:我如何讓其他應用程序在我的耐用服務上調用方法?現在我們使用一個超級複雜的自定義.NET Remoting庫。我想使用WCF,因爲過去對我們來說非常好。但是,這似乎並不是它通常解決的問題(至少不是簡單的方式) – Killnine

+0

如果實現所需的類來擴展WCF並傳遞任何服務需要或使用「靜態對象」方法我描述你應該能夠做到。換句話說,忘記你想要做什麼。相反,相反,忘記存在自動託管的解決方案,並使用Windows服務自行託管您的WCF。完成後,您只需將缺失的行爲添加到Windows服務。它非常可行。 – tucaz

0

你正試圖把一個方形釘放在一個圓孔中。

WCF明確地設計用於獨立於託管業務邏輯的方式調用業務邏輯。您正在嘗試維護在主機層中具有業務邏輯的舊遠程設計(在本例中爲Window的服務)。因此,您要求以WCF中可能的方式將信息傳回給主機,但又很醜陋,並且通常由於許多充分的原因而被避免。

如果你想要一個乾淨的WCF設計,你將需要創建抽象層並將業務邏輯移出現有的TestWindowsService類。然後,Windows服務創建WCF服務主機,WCF主機創建WCF服務,並且WCF服務不依賴於託管它的類。

說了這麼多......

要真正回答你的問題:

從概念上講,你所編寫的代碼應該工作。將對象實例傳遞到ServiceHost構造函數是迄今爲止避免編寫自定義IInstanceProvider的複雜性的最簡單方法。幾件事情要檢查:

  1. 當你傳遞一個服務實例到它需要被標記爲singleton ServiceHost的構造函數。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

  2. 確保初始化真正的工作方式,你認爲它是:

    1. 將保護你的TestService的(ITestWindowsService)構造函數如果服務爲空則拋出。
    2. 您對TestWcfService()的默認構造函數發表了「可發現性」的評論。我會刪除該構造函數(至少在您正在排除故障時)。一段代碼可能會使用該構造函數來託管您不需要的服務實例。這可能會導致您的應用程序開始拋出異常或編譯指出您真正問題的錯誤。

如果您仍然有問題:什麼是您的app.config的服務模式部分是什麼樣子?

+0

是的,通常當我覺得這種方式我知道我正在看問題的錯誤,也許WCF是不是要走的路。但MS吹捧WCF作爲.NET遠程處理的替代品,但它基本上不推薦使用此功能。我*知道*來自客戶端的調用正在執行默認構造函數。似乎我正在製作自託管端點,但無法訪問它......當我將默認ctr取出時,它會在我的客戶端進行有關缺少行爲的方法調用時引發錯誤。我已將我的服務模型添加到帖子中。 – Killnine

+0

當你拿出默認的構造函數時,錯誤是什麼?你真正的問題是你的配置需要修復,以免構造函數被調用。您可能需要將更改爲true以獲取更多信息給客戶端。 – ErnieL