【问题标题】:Using PerWcfSession lifestyle with Castle WCF Integration Facility将 PerWcfSession 生活方式与 Castle WCF 集成工具一起使用
【发布时间】:2012-08-03 20:48:24
【问题描述】:

以下代码使用 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 方法会导致以下错误:

无法获得组件 SelfHost.PerSession 的范围。这是最 可能是自定义 IScopeAccessor 中的错误,或者您正在尝试 访问范围之外的范围组件(如每个网络请求 Web 请求之外的组件等)

使用 PerWcfSession 组件的正确方法是什么?

【问题讨论】:

    标签: c# wcf castle-windsor wcffacility


    【解决方案1】:

    所以我遗漏了一些东西:

    ServiceContract需要设置SessionMode属性

    [ServiceContract(SessionMode = SessionMode.Required)]
    

    同样ServiceBehavior需要设置InstanceContextMode

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

    最后,服务注册需要更改 Lifestyle 的默认设置(Singleton),以便为每个请求重新创建它(并且重新评估依赖项)- Transient 或 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();
            }
        }
    }
    

    【讨论】:

    • 你在哪里定义“myBinding”和基地址?干杯
    • myBinding 在问题的 Program 类中定义
    • 感谢大卫的回复,我想你不能用这段代码更新你的答案吗?我自己在将绑定绑定到特定地址时遇到问题。干杯
    • 你去! “mybinding”只是绑定的名称。 .config 文件中没有其他任何定义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多