Служба поддержки MEF + WCF? - PullRequest
       13

Служба поддержки MEF + WCF?

6 голосов
/ 15 декабря 2009

Я только попал в MEF и столкнулся с проблемой, которую не могу решить. У меня есть служба Windows, которая читает в моих DLL (через MEF), и каждая DLL является хостом службы WCF. Когда я запускаю службу Windows и читаю в DLL, все работает нормально, за исключением того, что всякий раз, когда одна из библиотек WCF получает какую-либо «активность», она повторно создает экземпляр, а затем обрабатывает поступающие данные. Мне нужно, чтобы они просто один раз были созданы в начале. Возможно ли это?

Ответы [ 2 ]

4 голосов
/ 15 декабря 2009

Службы WCF по умолчанию на вызов режим экземпляра. Это означает, что новый экземпляр вашей службы WCF создается для каждого входящего вызова метода. Похоже, что вам нужен режим экземпляра singleton , но вы действительно хотите избежать этого, если проблема масштабируемости.

Способ, который я обошел, состоит в том, чтобы использовать режим экземпляра на вызов , но за сценой, к которой я синхронизирую доступ, есть статическое хранилище данных. Это, по крайней мере, позволяет клиентам подключаться, даже если им приходится на мгновение блокировать, когда хранилище данных используется после установления соединения.

Подробнее см. Справку MSDN по System.ServiceModel.InstanceContextMode .

4 голосов
/ 15 декабря 2009

Вы можете справиться с этим, внедрив 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) { }       
}
...