我有一个WCF服务合同,基本上是发布订阅者模式。
WCF服务托管在我要发布的Windows服务中。客户端订阅消息,当Windows服务执行某些操作时,它会发布给所有客户端。
为了托管服务,我已经声明了一个ServiceHost类,而Contract Class有一个方法,该方法没有在接口中标记,而是在要发布的类中实现。
我希望能够在本地调用此方法(不通过WCF),然后通过Callbacks发布消息。
我似乎无法从ServiceHost获得Contract Class的实例。
这有可能吗?如果可以的话怎么样?我知道解决方法是将一个客户端内置到服务中,但创建一个连接到自身的客户端似乎有点奇怪。
提前致谢
DJIDave
的app.config
<system.serviceModel>
<services>
<service behaviorConfiguration="Processor.Wcf.ServiceBehavior"
name="Processor.Wcf.ProcessorService">
<endpoint address="net.tcp://localhost:9000/processor/service"
binding="netTcpBinding" name="procService"
bindingConfiguration="netTcpBindingConfig"
contract="Processor.Wcf.IProcessorService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/Processor.Wcf/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Processor.Wcf.ServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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>
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfig"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transactionFlow="false"
transferMode="Buffered"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
listenBacklog="10"
maxBufferPoolSize="524288"
maxBufferSize="65536"
maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32"
maxStringContentLength="8192"
maxArrayLength="16384"
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
除非您将ServiceHost的服务实例引用作为构造函数参数提供,否则无法让ServiceHost为您提供服务实例引用。如果您确实提供了该实例引用,那么您正在创建一个通常不是一个好主意的单例服务。
要保持服务的配置,您必须通过客户端进行调用。这实际上比你想象的要容易。由于您的主机代码可以访问服务合同,因此您可以将其与ChannelFactory class一起使用以获取服务的代理。除服务合同外,您必须提供的只是端点名称,ChannelFactory将完成剩下的工作。以下是如何执行此操作的示例:
private IMyServiceContract GetLocalClient(string serviceEndpointName)
{
var factory = new ChannelFactory<IMyServiceContract>(serviceEndpointName);
return factory.CreateChannel();
}
更新:除了这种方法,您应该考虑让您服务公开NetNamedPipeBinding endpoint以提高性能。这种绑定几乎完成了内存中的所有操作,并且是同一机器服务调用的最快绑定。
对于多次实例化WCF服务(非单例),您可以维护一个列表,其中包含每个实例的相应回调函数,如下所示:mdsn。您可以直接从托管代码调用方法CallClients()(来自此MSDN示例),因为它是服务类的静态成员。这是我发现的唯一其他方式..
除非您将ServiceHost的服务实例引用作为构造函数参数提供,
Sixto解决方案的这一系列解决了我的问题。感谢并感谢this post。
我目前正在使用双面打包。
关键概念是你可以将Type
或实例传递给ServiceHost
构造函数。
所以我以前有:
ServiceHost host = new ServiceHost(typeof(MyService), myUri);
我需要的是:
MyService service = new MyService(foo); // Can now pass a parameter
ServiceHost host = new ServiceHost(service, myUri);
另外,我需要用MyService
标记
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
...现在我可以从服务中调用主机的方法。
但是,请记住,如果直接调用其方法,则您创建的实例将不具有OperationContext
:https://stackoverflow.com/a/15270541/385273
祝好运!
老问题,但here是另一种称为Singleton WCF Service hosted on a Windows Service
的方式
遵循@ Ben的要求,Service
需要被迫成为Singleton
:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
然后:
var host = new ServiceHost(typeof(MyService), myUri);
var instance = (MyService)host.SingletonInstance;
而已。基本上,主机已经有一个属性需要“铸造”才能访问Service
的所有功能。