是否可以在本地调用自承载 WCF 服务中的方法
本文关键字:WCF 服务 方法 调用 是否 | 更新日期: 2023-09-27 17:56:56
我有一个WCF服务协定,它基本上是发布订阅者模式。
WCF 服务承载在我要从中发布的 Windows 服务中。客户端订阅消息,当 Windows 服务执行某些操作时,它会发布到所有客户端。
为了托管服务,我已经声明了一个ServiceHost类,并且合约类有一个方法,该方法未在接口中标记,但在要发布的类中实现。
我希望能够在本地调用此方法(不通过 WCF),然后通过回调发布消息。
我似乎无法从服务主机访问合约类的实例。
这是否可能,如果可能,如何?我知道解决方法是将客户端也内置到服务中,但是创建一个客户端来连接到自身似乎有点奇怪。
提前致谢
DJIDave
应用配置
版<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>
服务主机的服务实例引用作为构造函数参数提供,否则无法让服务主机为您提供服务实例引用。如果您确实提供了该实例引用,那么您正在创建一个单一实例服务,这通常不是一个好主意。
若要保持服务按配置状态,必须通过客户端调用它。这实际上比您想象的要容易。由于主机代码有权访问服务协定,因此可以将其与 ChannelFactory 类一起使用,以获取服务的代理。除了服务合同之外,您只需要提供端点名称,ChannelFactory 将完成其余的工作。下面是如何执行此操作的示例:
private IMyServiceContract GetLocalClient(string serviceEndpointName)
{
var factory = new ChannelFactory<IMyServiceContract>(serviceEndpointName);
return factory.CreateChannel();
}
更新:除了此方法外,还应考虑让服务公开 NetNamedPipeBinding 终结点以提高性能。此绑定几乎可以执行内存中的所有操作,并且是同一计算机服务调用的最快绑定。
实例化的 WCF 服务(非单一实例),可以维护一个列表,其中包含每个实例的相应回调函数,如下所示:mdsn。可以直接从宿主代码调用方法 CallClients()(来自此 MSDN 示例),因为它是服务类的静态成员。这是我发现的唯一其他方法。
除非将服务主机的服务实例引用作为构造函数参数提供,
Sixto解决方案中的这句话为我解决了问题。感谢这篇文章。
我目前正在使用双工绑定。
关键概念是可以将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
祝你好运!
老问题,但这是另一种称呼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
访问所有功能。