2011-03-20 61 views
13

Estoy escribiendo una aplicación que expone un servicio a través de WCF. El servicio es autohospedado (aplicación de consola) y necesita usar una instancia de Singleton. Estoy tratando de averiguar cómo especificar singleton en la configuración del servicio sin usando atributos en la implementación del servicio. ¿Es posible especificar singleton en el código sin un atributo?Especifique un servicio Singleton en un servicio alojado de WCF

Gracias, Erick

Respuesta

22

Usted puede pasar a instancia del servicio a la ServiceHost constructor lugar de pasar a un tipo. En tal caso, su instancia aprobada se usará como singleton.

Editar:

Mi primera solución no funciona. Proporcionar instancia al constructor ServiceHost sigue requiriendo ServiceBehaviorAttribute con InstanceContextMode.Single. Pero éste debería funcionar:

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

ServiceBehaviorAttribute se incluye, aunque no se especifica tan sólo tiene que conseguirlo y modifique el valor por defecto.

+0

Soy nuevo en WCF y tengo un servicio WCF que quiero controlar con la configuración en lugar de metadatos en clase. Podría darnos detalles de su solución. – SJunejo

+0

Necesitaba forzar el 'InstanceContextMode' a' PerCall', y este método funciona para eso también. – Dan

0

Si desea mover esto en web.config o app.config, podría hacerlo con una costumbre BehaviorExtensionElement y IServiceBehavior:

El IServiceBehavior realmente analizar el valor de configuración en la enumeración y configurarlo (siguiendo @ respuesta 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; 
    } 
} 

el elemento de extensión le permite tirar de él desde config y lo pasa a 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; 
     } 
    } 
} 

Y a continuación, puede registrarlo en su configuración y utilizarla:

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