以下代码使用 CaSTLe Windsor 3.0 的 WCF Integration Facility注册 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 组件的正确使用方法是什么?
最佳答案
所以我遗漏了一些东西:
ServiceContract需要设置SessionMode属性
[ServiceContract(SessionMode = SessionMode.Required)]
同样,ServiceBehavior 需要设置 InstanceContextMode
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.PerSession)]
最后,服务注册需要更改默认的 Lifestyle(单例),以便为每个请求重新创建它(并重新评估依赖项)- Transient 或 PerWcfSession 都可以。
此外,因为我们需要一个 session ,绑定(bind)需要从 basicHttpBinding 更改为支持 session 的绑定(bind):
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();
}
}
}
关于c# - 将 PerWcfSession 生活方式与 CaSTLe WCF 集成工具结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11023491/