Specify a Singleton service in a WCF self hosted service

I am writing an application that exposes a service via WCF. The service is self-hosted (console app) and needs to use a Singleton instance. I am trying to figure out how to specify singleton in the service configuration without using attributes on the service implementation. Is it possible to specify singleton in code without an attribute?

Thanks, Erick

Answers


You can pass instance of the service to the ServiceHost constructor instead of passing a type. In such case your passed instance will be used as singleton.

Edit:

My former solution doesn't work. Providing instance to ServiceHost constructor still demands ServiceBehaviorAttribute with InstanceContextMode.Single. But this one should work:

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

ServiceBehaviorAttribute is included even if you don't specify it so you just need to get it and change default value.


If you want to move this into web.config or app.config, you could do so with a custom BehaviorExtensionElement and IServiceBehavior:

The IServiceBehavior will actually parse the value from config into the enum and set it (following @Ladislav's answer):

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;
    }
}

The extension element allows you to pull it from config and pass it to the 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;
        }
    }
}

And you can then register it in your config and use it:

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

Need Your Help

How do I apply CSS3 transition to all properties except background-position?

css3 css-transitions

I'd like to apply a CSS transition to all properties apart from background-position.

How to detect Facebook in-app browser?

javascript facebook mobile browser in-app

Have you had any experience in Facebook in-app browser detection?