2009-12-15 13 views
6

Ich komme gerade in MEF und ich bin auf ein Problem gestoßen, das ich nicht lösen kann. Ich habe einen Windows-Dienst, der in meinen DLLs (über MEF) liest und jede DLL ist ein WCF-Service-Host. Wenn ich meinen Windows-Dienst ausführe und die DLLs einlese, läuft alles gut, außer dass, wann immer eine der WCF-DLLs irgendeine "Aktivität" bekommt, sie die Daten wieder einführt und verarbeitet. Ich brauche sie nur einmal am Anfang zu instanziieren. Ist das möglich?MEF + WCF-Servicehost?

Antwort

4

WCF-Dienste standardmäßig auf ein pro Anruf Instanz-Modus. Dies bedeutet, dass eine neue Instanz Ihres WCF-Dienstes für jeden eingehenden Methodenaufruf instanziiert wird. Es klingt wie Sie wollen, ist ein Singleton Instanz-Modus, aber Sie wollen dies wirklich vermeiden, wenn die Problematik ist ein Problem.

Die Art, wie ich das geschafft habe, ist die pro Aufruf Instanz-Modus, aber habe einen statischen Datenspeicher hinter den Kulissen, die ich den Zugriff synchronisieren. Dies ermöglicht Clients zumindest eine Verbindung, selbst wenn sie kurzzeitig blockieren müssen, während der Datenspeicher verwendet wird, sobald die Verbindung hergestellt ist.

Weitere Informationen finden Sie in der MSDN-Hilfe unter System.ServiceModel.InstanceContextMode.

4

Sie können dies umgehen, indem sie ein IServiceBehavior und eine IInstanceProvider Umsetzung meiner implmentation von IServiceBehavior in OnStart Registrierung und mit IInstanceProvider für Sie Objektlebensdauer verwalten. Insbesondere können Sie eine Inversion des Steuercontainers verwenden, die dieselbe Instanz Ihres Diensttyps für jede Anforderung bereitstellt (d. H. Singleton-ähnliches Verhalten, ohne Singleton zu sein).

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) { }  
} 
+0

Ich denke, könnten Sie mir eine kleine Probe geben oder vielleicht ins Detail gehen. Ich bin auf keinen Fall ein Export in MEF oder WCF. – Travyguy9

+0

Ich habe eine Barebone-Implementierung von dem, worüber ich spreche, hinzugefügt. Der Schlüssel ist die Inversion des Steuercontainers, der die Lebensdauer des Objekts verwaltet. – jason

+0

In welcher Baugruppe befindet sich der IIocContainer? – Travyguy9