【问题标题】:Stop/start WCF MEX service at runtime在运行时停止/启动 WCF MEX 服务
【发布时间】:2009-02-13 19:17:32
【问题描述】:

是否可以/如何在运行时停止和启动自托管 WCF 服务的 HTTP MEX 侦听器而不影响主 WCF 服务?

(请不要问我为什么要这样做。这是一种绕过别人强加的人为限制的技巧。)

【问题讨论】:

  • 你会在哪里做呢?在您的自托管代码中?什么情况下?
  • 它将在自托管服务中。只要满足内部参数。
  • 一个简单但完整的代码答案已经发布。
  • 用修正的代码重新添加了我的答案,并更好地解释了它的假设。

标签: c# c#-3.0 wcf


【解决方案1】:

*****[重新测试和代码清理后重新添加此答案] 这是我添加到基于 WCF 的通用服务开发框架中的实际代码,并且已经过全面测试。*****

假设您从 ServiceHost 上启用 MEX 开始...

下面的解决方案写在 ServiceHost 子类的条款 (WCFServiceHost<T>) 实现 一个特殊的接口 (IWCFState) 存储 MEX 的一个实例 EndpointDispatcher 班级。

首先,添加这些命名空间...

using System.ServiceModel;
using System.ServiceModel.Dispatcher;

其次,定义IWCFState接口...

public interface IWCFState
{
    EndpointDispatcher MexEndpointDispatcher
    {
        get;
        set;
    }
}

第三,为一些ServiceHost扩展方法创建一个静态类(我们将在下面填写它们)...

public static class WCFExtensions
{
    public static void RemoveMexEndpointDispatcher(this ServiceHost host){}

    public static void AddMexEndpointDispatcher(this ServiceHost host){}
}

现在让我们填写扩展方法...

在运行时在 ServiceHost 上停止 MEX

public static void RemoveMexEndpointDispatcher(this ServiceHost host)
{
    // In the simple example, we only define one MEX endpoint for
    // one transport protocol
    var queryMexChannelDisps = 
            host.ChannelDispatchers.Where(
                disp => (((ChannelDispatcher)disp).Endpoints[0].ContractName
                                            == "IMetadataExchange"));
    var channelDisp = (ChannelDispatcher)queryMexChannelDisps.First();

    // Save the MEX EndpointDispatcher
    ((IWCFState)host).MexEndpointDispatcher = channelDisp.Endpoints[0];

    channelDisp.Endpoints.Remove(channelDisp.Endpoints[0]);
}

那就这样称呼吧……

// WCFServiceHost<T> inherits from ServiceHost and T is the Service Type,
// with the new() condition for the generic type T.  It encapsulates 
// the creation of the Service Type that is passed into the base class 
// constructor.
Uri baseAddress = new Uri("someValidURI");
WCFServiceHost<T> serviceImplementation = new WCFServiceHost<T>(baseAddress);

// We must open the ServiceHost first...
serviceImplementation.Open();

// Let's turn MEX off by default.
serviceImplementation.RemoveMexEndpointDispatcher();

在运行时在 ServiceHost 上(再次)启动 MEX

public static void AddMexEndpointDispatcher(this ServiceHost host)
{
    var queryMexChannelDisps =
            host.ChannelDispatchers.Where(
                    disp => (((ChannelDispatcher)disp).Endpoints.Count == 0));
    var channelDisp = (ChannelDispatcher)queryMexChannelDisps.First();

    // Add the MEX EndpointDispatcher
    channelDisp.Endpoints.Add(((IWCFState)host).MexEndpointDispatcher);
}

那就这样称呼吧……

serviceImplementation.AddMexEndpointDispatcher();

总结

此设计允许您使用一些消息传递方法向服务本身或托管服务的代码发送命令,并让它执行 MEX EndpointDispatcher 的启用或禁用,从而有效地关闭 MEX ServiceHost.

注意:此设计假定代码将在启动时支持 MEX,但随后它将使用配置设置来确定服务是否会在对 Open() 调用 ServiceHost 后禁用 MEX。如果您在打开 ServiceHost 之前尝试调用任一扩展方法,则会抛出此代码。

注意事项:我可能会创建一个特殊的服务实例,其管理操作在启动时不支持 MEX,并将其建立为服务控制通道。

资源

在解决这个问题时,我发现以下两个资源必不可少:

【讨论】:

  • 我对我的解决方案并不完全满意:1)我不喜欢假设只有 1 个 EndpointDispatcher 并指定 ContractName 而不是比较类型; 2) 我不喜欢假设 MEX ChannelDispatcher 有 0 个端点并且它是唯一这样的 ChannelDispatcher。
  • 我也不喜欢扩展方法本身,因为需要将转换嵌入到 IWCFSTate。因此,我可能只是将它们移到我的 WCFServiceHostUtils 静态类中。
  • 谢谢,这非常有帮助。我稍微修改了我的版本以支持多个 Mex 端点,它可以按需要工作。
  • 我很高兴!如果您有任何可能对您有进一步帮助的资源链接,例如支持多个 Mex 端点的方式,我很乐意看到这一点。干杯!
  • 我很确定我的“2 个 Mex 端点”只不过是我学习 WCF 的产物。实际上只暴露了 1 个 Mex 地址。
猜你喜欢
  • 2011-06-01
  • 1970-01-01
  • 2011-12-27
  • 2018-12-20
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2017-07-08
相关资源
最近更新 更多