6

我刚刚进入 MEF,遇到了一个我无法解决的问题。我有一个正在读取我的 DLL(通过 MEF)的 Windows 服务,每个 DLL 都是一个 WCF 服务主机。当我运行我的 Windows 服务并读取 DLL 时,一切都运行良好,除了每当其中一个 WCF DLL 获得任何“活动”时,它们就会重新实例化,然后处理传入的数据。我需要它们在开始时只实例化一次。这可能吗?

4

2 回答 2

4

您可以通过实现 anIServiceBehavior和 an IInstanceProvider、注册我对IServiceBehaviorin的实现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) { }       
}
于 2009-12-15T16:41:08.417 回答
4

WCF 服务默认为按调用实例模式。这意味着每次传入的方法调用都会实例化 WCF 服务的新实例。听起来您想要的是单例实例模式,但如果可伸缩性是一个问题,您真的想避免这种情况。

我解决这个问题的方法是使用每次调用实例模式,但在我同步访问的幕后有一个静态数据存储。这至少允许客户端进行连接,即使在建立连接后他们必须在数据存储正在使用时暂时阻塞。

有关更多详细信息,请参阅有关System.ServiceModel.InstanceContextMode的 MSDN 帮助。

于 2009-12-15T16:41:54.217 回答