在 WCF 自托管服务中指定 Singleton 服务

Posted

技术标签:

【中文标题】在 WCF 自托管服务中指定 Singleton 服务【英文标题】:Specify a Singleton service in a WCF self hosted service 【发布时间】:2011-07-19 08:05:40 【问题描述】:

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

谢谢, 埃里克

【问题讨论】:

【参考方案1】:

您可以将服务实例传递给ServiceHost constructor,而不是传递类型。在这种情况下,您传递的实例将用作单例。

编辑:

我以前的解决方案不起作用。向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 服务,我想通过配置而不是类上的元数据来控制它。您能否提供解决方案的详细信息。 我需要将InstanceContextMode 强制为PerCall,这个方法也适用。【参考方案2】:

如果您想将其移动到 web.configapp.config,您可以使用自定义 BehaviorExtensionElementIServiceBehavior

IServiceBehavior 实际上会将 config 中的值解析到枚举中并设置它(按照@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"/>

【讨论】:

以上是关于在 WCF 自托管服务中指定 Singleton 服务的主要内容,如果未能解决你的问题,请参考以下文章

WCF:未提供服务证书。在 ServiceCredentials 中指定服务证书

我们是不是需要在 WCF 服务器和客户端中指定相同的绑定?

如何在 WCF 测试客户端 (WcfTestClient.exe) 中指定列表参数?

如何为自托管 WCF 服务启用跨域调用

我可以在 Windows 服务中托管(自托管)WCF 服务并通过 http 公开它吗?

自托管 WCF 服务:如何从托管应用程序访问实现服务合同的对象?