*****[重新测试和代码清理后重新添加此答案] 这是我添加到基于 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,并将其建立为服务控制通道。
资源
在解决这个问题时,我发现以下两个资源必不可少: