***** [Повторно добавьте этот ответ после повторного тестирования и очистки кода] Это реальный код, который я добавил в мою общую инфраструктуру разработки служб на основе WCF, и он полностью протестирован. *****
Предполагается, что вы начинаете с включенным MEX на ServiceHost
...
Следующее решение написано в
условия подкласса 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){}
}
Теперь давайте заполним методы расширения ...
Остановка MEX на ServiceHost
во время выполнения
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();
Запуск MEX (снова) на ServiceHost
во время выполнения
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 при запуске, но затем он будет использовать настройку конфигурации, чтобы определить, отключит ли служба MEX после вызова Open()
на ServiceHost
. Этот код будет выдан, если вы попытаетесь вызвать любой из методов расширения до открытия ServiceHost
.
Соображения: Я бы, вероятно, создал специальный экземпляр службы с операциями управления, которые не поддерживают MEX при запуске, и установил бы его в качестве канала управления службами.
Ресурсы
Я нашел следующие два ресурса, необходимые для выяснения этого: