在WCF自托管服务中指定一个单例服务。

13

我正在编写一款通过WCF公开服务的应用程序。该服务是自承载的(控制台应用程序),需要使用单例实例。我正试图弄清楚如何在服务配置中指定单例,而不使用服务实现上的属性。是否可能在代码中指定单例而不使用属性?

谢谢, Erick

2个回答

22
你可以将服务的实例传递给ServiceHost构造函数,而不是传递类型。在这种情况下,您传递的实例将被用作单例。

编辑:

我的前一种解决方案不起作用。向ServiceHost构造函数提供实例仍然需要ServiceBehaviorAttributeInstanceContextMode.Single。但是这样应该行得通:

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

即使您没有指定,ServiceBehaviorAttribute也会被包含,因此您只需要获取它并更改默认值。


我对WCF还很陌生,我有一个WCF服务,我想通过配置来控制它,而不是在类元数据上。您能否提供您的解决方案的详细信息? - SJunejo
我需要强制将 InstanceContextMode 设置为 PerCall,而这种方法也适用于此。 - Dan

0
如果您想将此移动到web.configapp.config中,可以使用自定义的BehaviorExtensionElementIServiceBehavior来实现: IServiceBehavior将从配置中解析值并将其设置为枚举(遵循@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;
    }
}

扩展元素允许您从配置中提取它并将其传递给 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;
        }
    }
}

然后您可以在配置文件中注册并使用它:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接