Я только начинаю работать с MEF и столкнулся с проблемой, которую не могу решить. У меня есть служба Windows, которая читает мои библиотеки DLL (через MEF), и каждая библиотека DLL является узлом службы WCF. Когда я запускаю свою службу Windows и читаю библиотеки DLL, все работает нормально, за исключением того, что всякий раз, когда одна из библиотек WCF получает какую-либо «активность», они повторно создают экземпляры, а затем обрабатывают поступающие данные. Мне нужно, чтобы они просто создавали экземпляр один раз в начале. Это возможно?
Хост службы MEF + WCF?
Ответы (2)
Службы WCF по умолчанию используют режим экземпляра на вызов. Это означает, что новый экземпляр службы WCF создается для каждого входящего вызова метода. Похоже, что вам нужен режим экземпляра singleton, но вы действительно хотите избежать этого, если масштабируемость является проблемой.
Способ, которым я обошел это, заключается в использовании режима экземпляра per call, но за кулисами у меня есть хранилище статических данных, к которому я синхронизирую доступ. По крайней мере, это позволяет клиентам подключаться, даже если им приходится на мгновение блокироваться, пока хранилище данных используется после установления соединения.
См. справку MSDN в System.ServiceModel.InstanceContextMode для более подробной информации.
Вы можете справиться с этим, внедрив IServiceBehavior
и IInstanceProvider
, зарегистрировав мою реализацию IServiceBehavior
в OnStart
и IInstanceProvider
управляя временем жизни объекта для вас. В частности, вы можете использовать инверсию контейнера управления, который обслуживает один и тот же экземпляр вашего типа службы при каждом запросе (т. е. одноэлементное поведение, но не одноэлементное).
public partial class MyServiceHost : ServiceBase {
// details elided
protected override void OnStart(string[] args) {
this.Host = new ServiceHost(typeof(MySerivce));
this.Host.Description.Behaviors.Add(new MyServiceBehavior());
this.Host.Open();
}
}
public class MyServiceBehavior : IServiceBehavior {
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters
) { }
public void ApplyDispatchBehavior(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase) {
IIoCContainer container = new IocContainer();
foreach (var cdBase in serviceHostBase.ChannelDispatchers) {
ChannelDispatcher cd = cdBase as ChannelDispatcher;
if (cd != null) {
foreach (EndpointDispatcher ed in cd.Endpoints) {
ed.DispatchRuntime.InstanceProvider = new MyInstanceProvider(
container,
serviceDescription.ServiceType
);
}
}
}
}
public void Validate(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase
) { }
}
public class MyInstanceProvider : IInstanceProvider {
readonly IIocContainer _container;
readonly Type _serviceType;
public InstanceProvider(IIoCContainer container, Type serviceType) {
_container = container;
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext, Message message) {
return _container.Resolve(_serviceType);
}
public object GetInstance(InstanceContext instanceContext) {
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance) { }
}
IIoCContainer
создан, но вы можете использовать любую инверсию контейнера управления (например, Castle Windsor, StructureMap или Unity).
- person jason; 15.12.2009