是否可以在本地调用自承载 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>

是否可以在本地调用自承载 WCF 服务中的方法

除非将

服务主机的服务实例引用作为构造函数参数提供,否则无法让服务主机为您提供服务实例引用。如果您确实提供了该实例引用,那么您正在创建一个单一实例服务,这通常不是一个好主意。

若要保持服务按配置状态,必须通过客户端调用它。这实际上比您想象的要容易。由于主机代码有权访问服务协定,因此可以将其与 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访问所有功能。