【问题标题】:How do I get a reference to a WCF service object from the code that creates it?如何从创建 WCF 服务对象的代码中获取对它的引用?
【发布时间】:2023-03-18 15:19:01
【问题描述】:

我正在修改 the code in this tutorial 以构建一些基本的订阅推送 wcf 客户端/服务器类,但我只是碰了壁。

本教程中的服务器类是使用以下代码创建的:

class Program
  {
    static void Main(string[] args)
    {
      using (ServiceHost host = new ServiceHost(
        typeof(StringReverser),
        new Uri[]{
          new Uri("net.pipe://localhost")
        }))
      {

        host.AddServiceEndpoint(typeof(IStringReverser),
          new NetNamedPipeBinding(),
          "PipeReverse");

        host.Open();

        Console.WriteLine("Service is available. " +
          "Press <ENTER> to exit.");
        Console.ReadLine();

        host.Close();
      }
    }
  }

我假设发布了一个 StringReverser 的实例,我的问题是我需要对该实例的引用,以便我可以在其上调用一个方法将数据推送回客户端。

在本教程中,服务器只是使用回调方法回复客户端,而不是将对客户端的引用存储在订阅者列表中。当我需要将数据推送回客户端时,我需要一个对 Service 对象的引用,以便我可以实际使用回调。

有没有办法使用 WCF 发布服务,让您可以引用服务对象?或者我可以从 host 对象中获取对服务对象的引用吗?

任何帮助将不胜感激......

【问题讨论】:

  • 当您说“主机”对象时,您是指服务实现吗?您究竟需要在哪里引用它?
  • 我需要从发布服务的代码中引用服务实现。这样我就可以定期调用它的方法来向任何订阅了数据的客户端发送数据。
  • 基本上上面的 Main 方法会在 dataPropogator 类的构造函数中,服务实现通过 wcf 接受订阅调用,并且当调用 dataPropogator calss 上的方法时,它会向所有订阅者发送数据.我需要一个对服务对象的引用来做回调

标签: c# wcf


【解决方案1】:

您可以在 StringReverser 类中使用单例模式并将其实例传递给 ServiceHost 构造函数:

ServiceHost host = new ServiceHost(
  StringReverser.Instance,
  new Uri[]{new Uri("net.pipe://localhost")}
);

【讨论】:

  • 我可以创建一个 StringReverser 实例并将其传入,而不是传递一个单例。
  • 这看起来是最好的解决方案。
【解决方案2】:

我同意 Julien 的回答是正确的方法,但它是不完整的(至少对于 .NET 4.5)。传入服务实例后,必须将ServiceHost 的实例上下文模式设置为Single。如果不这样做,在调用ServiceHost Open() 方法时会报错。

设置上下文模式的方法并不明显。这是我的一个程序的片段,取自不同的 SO 答案:

var baseAddress = new Uri("http://localhost:15003/MockGateway");

using (var host = new ServiceHost(new MockGatewayService(), baseAddress))
{
    // Since we are passing an instance of the service into ServiceHost (rather 
    // than passing in the type) we have to set the context mode to single.
    var behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
    behavior.InstanceContextMode = InstanceContextMode.Single;

    // Continue to use the service here.  If you ever need to get a reference
    // to the service object you can do so with...
    MockGatewayService myService = host.SingletonInstance as MockGatewayService;

    // ...
}

【讨论】:

    【解决方案3】:

    在您的服务合同中,您可以调用

    OperationContext.Current.GetCallbackChannel());

    在服务连接后调用的任何方法中,然后将其传递出服务合同。我通常有一个 join 方法,我可以在其中获取客户端的 guid 并在那里获取回调。这比看起来更难。您要么需要一个单例/全局变量来将其取出(简单),要么您需要制作它以便 WCF 可以使用参数化构造函数(困难)。对于后者,更正确的做法是,您需要推出自己的实现 IInstanceProvider 和 IEndPointBehavior 的类,并将您的行为添加到您感兴趣的端点。这具有允许您使用具有不同端点的不同构造函数的额外好处无需重新定义您的合同。不幸的是,没有类型安全的方法可以做到这一点,因为您将不得不使用反射。抱歉,我无法提供样品,但我拥有的一切都是专有的。

    【讨论】:

    • 谢谢,但这并没有让我获得对客户端而不是服务器的引用,我需要对我刚刚在 program.cs 中创建的 StringReverser 的引用,而不是调用服务的客户端对象。
    • 对不起,您可以将 stringreverser 作为构造函数参数传入。如果您遵循公认的答案,则 WCF 只能使用您的类的一个实例。这会影响您的并发模型和性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 2011-05-25
    • 2011-11-10
    • 2013-02-14
    • 2011-03-05
    相关资源
    最近更新 更多