引用Windows服务的WCF调用

时间:2013-01-23 18:40:02

标签: c# .net wcf 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成员尚未设置。

我一直在寻找解决方案,并发现了一些引用ServiceHostFactoryServiceHost以及IInstanceProvider,但每个都看起来非常非常复杂。

您可以提供的任何想法都会非常感激。

编辑:这是我的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>

1 个答案:

答案 0 :(得分:0)

你正试图在一个圆孔中放一个方形钉。

WCF明确设计为能够独立于托管方式调用业务逻辑。您正在尝试维护在主机层中具有业务逻辑的旧远程处理设计(在本例中为Window的服务)。因此,您要求以WCF中可能的方式将信息传递回主机,但是丑陋并且通常由于很多原因而被避免。

如果您需要干净的WCF设计,则需要创建抽象层并将业务逻辑移出现有的TestWindowsService类。然后,Windows服务创建WCF服务主机,WCF主机创建WCF服务,WCF服务不依赖于托管它的类。

说完了所有......

要真正回答您的问题:

从概念上讲,您编写的代码应该有效。将对象实例传递到ServiceHost构造函数是迄今为止避免编写自定义IInstanceProvider的复杂性的最简单方法。要检查的几件事情:

  1. 将服务实例传递到ServiceHost构造函数时,需要将其标记为singleton

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

  2. 确保初始化确实按照您的想法运行:

    1. 在ServiceService(ITestWindowsService)构造函数上设置一个保护程序,如果service为null,则抛出该构造函数。
    2. 您对TestWcfService()的默认构造函数有一个评论,该构造函数表示“可发现性”。我会删除该构造函数(至少在您进行故障排除时)。一段代码可能正在使用该构造函数来托管您不想要的服务实例。这可能会导致您的应用程序开始抛出异常或编译指出您真正问题的错误。
  3. 如果您仍然遇到问题:app.config的服务模型部分是什么样的?