2012-06-13 28 views
3

下面的代碼使用的溫莎城堡3.0的WCF Integration Facility註冊一個WCF自託管服務:使用PerWcfSession生活方式城堡WCF集成工具

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel; 

using Castle.Facilities.WcfIntegration; 
using Castle.MicroKernel.Registration; 
using Castle.Windsor; 

namespace SelfHost 
{ 
    [ServiceContract] 
    public interface IHelloWorldService 
    { 
     [OperationContract] 
     string SayHello(string name); 
    } 

    [ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
    public class HelloWorldService : IHelloWorldService 
    { 
     private readonly PerSession _perSession; 

     public HelloWorldService(PerSession perSession) 
     { 
      _perSession = perSession; 
     } 

     public string SayHello(string name) 
     { 
      return string.Format("Hello, {0} {1}", name, _perSession.Info()); 
     } 
    } 

    public class PerSession 
    { 
     private readonly string _now; 

     public PerSession() 
     { 
      _now = DateTime.Now.ToString(); 
     } 

     public string Info() 
     { 
      return _now; 
     } 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      Uri baseAddress = new Uri("http://localhost:8080/hello"); 

      var container = new WindsorContainer(); 

      container.AddFacility<WcfFacility>(); 

      container.Register(
       Component.For<PerSession>().LifeStyle.PerWcfSession(), 
       Component.For<IHelloWorldService>() 
        .ImplementedBy<HelloWorldService>() 
        .AsWcfService(
         new DefaultServiceModel() 
          .AddBaseAddresses(baseAddress) 
          .AddEndpoints(WcfEndpoint.BoundTo(new BasicHttpBinding()).At("basic")) 
          .PublishMetadata(o => o.EnableHttpGet()) 
        ) 
       ); 

      Console.WriteLine("The service is ready at {0}", baseAddress); 
      Console.WriteLine("Press <Enter> to stop the service."); 
      Console.ReadLine(); 
     } 
    } 
} 

試圖調用使用WcfTestClient.exe導致SayHello方法出現以下錯誤:

Could not obtain scope for component SelfHost.PerSession. This is most likely either a bug in custom IScopeAccessor or you're trying to access scoped component outside of the scope (like a per-web-request component outside of web request etc)

什麼是使用PerWcfSession組件的正確方法?

回答

2

所以我錯過了幾件事情:

的的ServiceContract需要設置SessionMode屬性

[ServiceContract(SessionMode = SessionMode.Required)] 

同樣的ServiceBehavior需要設置InstanceContextMode

[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.PerSession)] 

最後,服務註冊需要從默認(Singleton)更改生活方式,以便它爲每個請求重新創建(並重新評估依賴關係特德) - 瞬態或PerWcfSession將工作。

而且,因爲我們需要一個會議上,結合需要從basicHttpBinding的改變的東西,支持會話:

Component.For<IHelloWorldService>() 
    .ImplementedBy<HelloWorldService>() 
    .LifestyleTransient() 
    .AsWcfService(
     new DefaultServiceModel() 
      .AddBaseAddresses(baseAddress) 
      .AddEndpoints(WcfEndpoint.BoundTo(new WSHttpBinding()).At("myBinding")) 
      .PublishMetadata(o => o.EnableHttpGet()) 
    ) 

這使得最終的代碼如下所示:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.ServiceModel; 

using Castle.Facilities.WcfIntegration; 
using Castle.MicroKernel.Registration; 
using Castle.Windsor; 

namespace SelfHost 
{ 
    [ServiceContract(SessionMode = SessionMode.Required)] 
    public interface IHelloWorldService 
    { 
     [OperationContract] 
     string SayHello(string name); 
    } 

    [ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.PerSession)] 
    public class HelloWorldService : IHelloWorldService 
    { 
     private readonly PerSession _perSession; 

     public HelloWorldService(PerSession perSession) 
     { 
      _perSession = perSession; 
     } 

     public string SayHello(string name) 
     { 
      return string.Format("Hello, {0} {1}", name, _perSession.Info()); 
     } 
    } 

     public class PerSession 
     { 
      private readonly string _now; 

      public PerSession() 
      { 
       _now = DateTime.Now.ToString(); 
      } 

      public string Info() 
      { 
       return _now; 
      } 
     } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      Uri baseAddress = new Uri("http://localhost:8080/hello"); 

      var container = new WindsorContainer(); 

      container.AddFacility<WcfFacility>(); 

      container.Register(
       Component.For<PerSession>().LifeStyle.PerWebRequest, 
       Component.For<IHelloWorldService>() 
        .ImplementedBy<HelloWorldService>() 
        .LifeStyle.PerWebRequest 
        .AsWcfService(
         new DefaultServiceModel() 
          .AddBaseAddresses(baseAddress) 
          .AddEndpoints(WcfEndpoint.BoundTo(new WSHttpBinding()).At("myBinding")) 
          .PublishMetadata(o => o.EnableHttpGet()) 
        ) 
       ); 

      Console.WriteLine("The service is ready at {0}", baseAddress); 
      Console.WriteLine("Press <Enter> to stop the service."); 
      Console.ReadLine(); 
     } 
    } 
} 
+0

哪裏你在定義「myBinding」和基地址嗎?乾杯 – M05Pr1mty

+0

myBinding在程序類中定義的問題 –

+0

感謝David的回覆,我不認爲你可以用這段代碼更新你的答案嗎?我有問題自己得到綁定綁定到一個特定的地址。乾杯 – M05Pr1mty