我可以在本地调用自托管 WCF 服务中的方法吗?
我有一个 WCF 服务合同,它基本上是发布订阅者模式。
WCF 服务托管在我想要从中发布的 Windows 服务内。客户端订阅消息,当 Windows 服务执行某些操作时,它会发布给所有客户端。
为了托管服务,我声明了一个 ServiceHost 类,并且 Contract 类有一个方法,该方法未在接口中标记,但在要发布的类中实现。
我希望能够在本地调用此方法(不通过 WCF),然后通过回调发布消息。
我似乎无法从 ServiceHost 访问 Contract 类的实例。
这可能吗?如果可能的话怎么办?我知道解决方法是将客户端也内置到服务中,但创建客户端来连接到自身似乎有点奇怪。
预先感谢
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>
I have a WCF Service contract which is basically the Publish Subscriber pattern.
The WCF Service is hosted inside the Windows Service that I want to publish from. The Clients subscribe to messages and when the Windows Service does something it publishes to all clients.
To host the service I have declared a ServiceHost class and the Contract Class has a method which is not flagged in the Interface but is implemented in the Class to publish.
I want to be able to call this method locally (not going through WCF) which then publishes the message via Callbacks.
I can't seem to get from ServiceHost to the instance of the Contract Class.
Is this possible and if so how? I know the work around is to have a client built into the service as well, but it seems a bit strange creating a client to connect to itself.
Thanks in advance
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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
除非您将服务实例引用作为构造函数参数提供给 ServiceHost,否则无法让 ServiceHost 为您提供服务实例引用。如果您确实提供了该实例引用,那么您正在创建一个单例服务,这通常不是一个好主意。
要保持服务的配置,您必须通过客户端调用它。这实际上比您想象的要容易。由于您的主机代码可以访问服务合同,因此您可以将其与 ChannelFactory 类 一起使用来获取该服务的代理。除了服务合同之外,您只需提供端点名称,ChannelFactory 将完成其余的工作。以下是如何执行此操作的示例:
更新:
除了这种方法之外,您还应该考虑让您的服务向提高性能。此绑定几乎在内存中执行所有操作,并且是同一机器服务调用的最快绑定。
Unless you provide the service instance reference to the ServiceHost as a constructor parameter, there isn't a way to have the ServiceHost provide you an service instance reference. If you do provide that instance reference then you are creating a singleton service which is generally not a good idea.
To keep the service as it is configured, you will have to call it through a client. This is actually easier than you might think. Since your host code has access to the service contract, you can use it with the ChannelFactory class to get a proxy for the service. Besides the service contract, all you have to provide is the endpoint name and ChannelFactory will do the rest. Below is an example of how to do this:
UPDATE:
Along with this approach, you should consider having you service expose a NetNamedPipeBinding endpoint to improve performance. This binding pretty much does everything in memory and is the fastest binding for same machine service invocation.
对于实例化多次(非单例)的 WCF 服务,您可以维护一个包含每个实例相应回调函数的列表,如下所示:mdsn。您可以直接从托管代码调用方法CallClients()(来自此 MSDN 示例),因为它是服务类的静态成员。这是我发现的唯一其他方法..
For a WCF service instantiating more than once (non-singleton), you can maintain a list containing each instance's corresponding callback function as given here: mdsn. You can call the method CallClients() (from this MSDN example) from the hosting code directly as it is a static member of the service class. This is the only other way I found..
Sixto 解决方案中的这一行为我解决了问题。感谢 这篇文章也是如此。
我现在使用的是双面装订。
关键概念是您可以将
Type
或实例传递给ServiceHost
构造函数。所以我之前的情况是:
我需要的是:
另外,我需要用
... 标记
MyService
,现在我可以从服务内部调用主机的方法。但是,请记住,如果您直接调用其方法,您创建的实例将不会有
OperationContext
:https ://stackoverflow.com/a/15270541/385273祝你好运!
This line from Sixto's solution solved things for me. Credit and thanks to this post as well.
I'm using a duplex binding at the moment.
The key concept is that you can pass in a
Type
or an instance to theServiceHost
constructor.So what I had before was:
What I needed was:
Also, I needed to mark
MyService
with...and now I can call the host's methods from inside the service.
However, keep in mind that the instance you created will not have an
OperationContext
if you call its methods directly: https://stackoverflow.com/a/15270541/385273Good luck!
老问题,但是 这里是调用Windows服务上托管的
单例WCF服务
的另一种方法,按照@Ben的要求,
Service
将需要强制成为Singleton
:然后:
就是这样。基本上,主机已经拥有一个需要“强制转换”的属性,以便能够访问
Service
中的所有功能。Old question, but here is another way to call a
Singleton WCF Service hosted on a Windows Service
Following @Ben's requirements, the
Service
would need to be forced to be aSingleton
:Then:
That's it. Basically, the host already has a property that needs to be 'casted' to be able to access all the features from the
Service
.