【问题标题】:MEF + WCF Service Host?MEF + WCF 服务主机?
【发布时间】:2009-12-15 16:33:28
【问题描述】:

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

【问题讨论】:

    标签: c# wcf mef


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      您可以通过实现IServiceBehaviorIInstanceProvider、在OnStart 中注册我对IServiceBehavior 的实现以及让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) { }       
      }
      

      【讨论】:

      • 我想你能给我一个小样本或者更详细一点。我绝不是 MEF 或 WCF 的出口商。
      • 我添加了我正在谈论的内容的准系统实现。关键是管理对象生命周期的控制容器的反转。
      • IIocContainer 位于哪个程序集?
      • 这由您决定。 IIoCContainer 已组成,但您可以使用任何控制容器的反转(例如,Castle Windsor、StructureMap 或 Unity)。
      • 我环顾四周,发现我的 Windows 服务读取的 WCF 服务的 AppDomain ID 为 1,然后收到数据传入通知的 WCF 服务有一个 AppDomain ID 为 2。您给我的解决方案(我认为是在 WindowService 上)是否保证我将始终使用 AppDomain 为 1 的解决方案?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 2010-12-07
      • 2010-10-19
      • 1970-01-01
      相关资源
      最近更新 更多