2011-03-20 3 views
13

J'écris une application qui expose un service via WCF. Le service est auto-hébergé (application de console) et doit utiliser une instance de Singleton. J'essaie de comprendre comment spécifier singleton dans la configuration du service sans en utilisant des attributs sur l'implémentation du service. Est-il possible de spécifier singleton dans le code sans attribut?Spécifier un service Singleton dans un service hébergé WCF

Merci, Erick

Répondre

22

Vous pouvez passer par exemple du service à la ServiceHost constructor au lieu de passer un type. Dans ce cas, votre instance passée sera utilisée comme singleton.

Edit:

Mon ancienne solution ne fonctionne pas. Fournir une instance au constructeur ServiceHost exige toujours ServiceBehaviorAttribute avec InstanceContextMode.Single. Mais celui-ci devrait fonctionner:

var host = new ServiceHost(typeof(Service)); 
var behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>(); 
behavior.InstanceContextMode = InstanceContextMode.Single; 
host.Open(); 

ServiceBehaviorAttribute est inclus, même si vous ne spécifiez pas si vous avez juste besoin de l'obtenir et le changement valeur par défaut.

+0

Je suis nouveau à WCF et j'ai un service WCF que je veux contrôler la configuration au lieu de métadonnées de la classe. Pourriez-vous s'il vous plaît fournir des détails de votre solution. – SJunejo

+0

J'avais besoin de forcer 'InstanceContextMode' à' PerCall', et cette méthode fonctionne aussi pour ça. – Dan

0

Si vous voulez déplacer cela dans web.config ou app.config, vous pouvez le faire avec une coutume BehaviorExtensionElement et IServiceBehavior:

Le IServiceBehavior analysera en fait la valeur de config dans le ENUM et mettez-le (suivant @ réponse de Ladislav):

public class InstanceContextServiceBehavior : IServiceBehavior 
{ 
    InstanceContextMode _contextMode = default(InstanceContextMode); 

    public InstanceContextServiceBehavior(string contextMode) 
    { 
     if (!string.IsNullOrWhiteSpace(contextMode)) 
     { 
      InstanceContextMode mode; 

      if (Enum.TryParse(contextMode, true, out mode)) 
      { 
       _contextMode = mode; 
      } 
      else 
      { 
       throw new ArgumentException($"'{contextMode}' Could not be parsed as a valid InstanceContextMode; allowed values are 'PerSession', 'PerCall', 'Single'", "contextMode"); 
      } 
     } 
    } 

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
     var behavior = serviceDescription.Behaviors.Find<ServiceBehaviorAttribute>(); 
     behavior.InstanceContextMode = _contextMode; 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     return; 
    } 

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     return; 
    } 
} 

l'élément d'extension permet de le retirer de la configuration et de passer à la IServiceBehavior:

public class InstanceContextExtensionElement : BehaviorExtensionElement 
{ 
    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(InstanceContextServiceBehavior); 
     } 
    } 

    protected override object CreateBehavior() 
    { 
     return new InstanceContextServiceBehavior(ContextMode); 
    } 

    const object contextMode = null; 

    [ConfigurationProperty(nameof(contextMode))] 
    public string ContextMode 
    { 
     get 
     { 
      return (string)base[nameof(contextMode)]; 
     } 
     set 
     { 
      base[nameof(contextMode)] = value; 
     } 
    } 
} 

Et vous pouvez l'enregistrer dans votre config et de l'utiliser:

<extensions> 
    <behaviorExtensions> 
    <add name="instanceContext" type="FULLY QUALFIED NAME TO CLASS"/> 
    </behaviorExtensions> 
</extensions> 
... 
    <serviceBehaviors> 
    <behavior name="Default"> 
     <instanceContext contextMode="Single"/> 
Questions connexes