我有一个长期运行的服务,它从一个源获取数据,操作它,将它存储在数据库中等。
我想将该服务的一些方法暴露给其他应用程序。目前我们通过.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
成员尚未设置。
我一直在寻找解决方案,并发现了一些引用ServiceHostFactory
和ServiceHost
以及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>
答案 0 :(得分:0)
你正试图在一个圆孔中放一个方形钉。
WCF明确设计为能够独立于托管方式调用业务逻辑。您正在尝试维护在主机层中具有业务逻辑的旧远程处理设计(在本例中为Window的服务)。因此,您要求以WCF中可能的方式将信息传递回主机,但是丑陋并且通常由于很多原因而被避免。
如果您需要干净的WCF设计,则需要创建抽象层并将业务逻辑移出现有的TestWindowsService类。然后,Windows服务创建WCF服务主机,WCF主机创建WCF服务,WCF服务不依赖于托管它的类。
说完了所有......
要真正回答您的问题:
从概念上讲,您编写的代码应该有效。将对象实例传递到ServiceHost构造函数是迄今为止避免编写自定义IInstanceProvider的复杂性的最简单方法。要检查的几件事情:
将服务实例传递到ServiceHost构造函数时,需要将其标记为singleton。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
确保初始化确实按照您的想法运行:
如果您仍然遇到问题:app.config的服务模型部分是什么样的?