2011-03-20 70 views
13

我正在編寫一個通過WCF公開服務的應用程序。該服務是自託管的(控制檯應用程序),需要使用Singleton實例。我正在試圖找出如何在服務配置中使用服務實現上的屬性指定單身人士,而不使用。是否可以在沒有屬性的代碼中指定單例?在WCF自託管服務中指定單例服務

感謝, 埃裏克

回答

22

您可以通過服務的實例的 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即使你不指定,所以你只需要得到它,並更改默認值是包括在內。

+0

我是新來的WCF和我有我想與配置,而不是在類的元數據來控制WCF服務。您能否提供您的解決方案的詳細信息。 – SJunejo 2012-04-25 21:55:58

+0

我需要強制'InstanceContextMode'到'PerCall',並且這個方法也適用於這個。 – Dan 2013-03-11 17:31:12

0

如果你想這個遷入web.configapp.config,你可以使用自定義BehaviorExtensionElementIServiceBehavior這樣做:

IServiceBehavior真正分析從配置的值置於枚舉並設置(以下@拉吉斯拉夫的答案):

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"/>