【问题标题】:Wcf with SimpleInjector throws "WCF scopes can not be nested"带有 SimpleInjector 的 Wcf 抛出“WCF 范围不能嵌套”
【发布时间】:2013-06-15 21:30:42
【问题描述】:

服务层分为命令端和查询端,每一端都有自己的处理程序。

使用如下配置

// EF context
_container.RegisterPerWcfOperation<MyDbContext, MyDbContext>();
_container.RegisterManyForOpenGeneric(typeof(IHandler<>),
    ApplicationAssemblies);

// many more regs but nothing special

SimpleInjectorServiceHostFactory.SetContainer(_container);

以及所需的标记设置:

Factory="SimpleInjector.Integration.Wcf.SimpleInjectorServiceHostFactory, SimpleInjector.Integration.Wcf"

抛出以下异常:

WCF 范围不能嵌套。

我认为错误发生在

internal WcfOperationScope BeginScope()

WcfOperationScopeManager 的实现。

一些背景资料:

  • WinForm 应用程序
  • QueryClient 的执行由后台工作人员完成
  • 我正在使用 Simple Injector 2.2.3 版
  • 构建容器的 Global.asax
  • 托管在 IIS 中
  • 每个 .svc 都将其标记设置为使用 SimpleInjectorFactory
  • wsHttpBinding 带证书和自定义 UserNamePasswordValidator
  • 每个端点配置都将所有需要的值设置为 2147483647。

当我连续快速执行两个加载请求时出现错误,所以第一个没有完成,第二个发生了。

【问题讨论】:

    标签: wcf dependency-injection ioc-container simple-injector lifetime-scoping


    【解决方案1】:

    对于某些 WCF 配置,这是 Simple Injector 2.2.3 的一个已知问题。某些 WCF 配置会强制对 IInstanceProvider.GetInstance 进行第二次调用。 SimpleInjectorInstanceProvider.GetInstance 方法调用内部的BeginScope 方法,该方法仅限于一个作用域。

    有两种解决方案:

    第一个解决方案是升级到最新的Simple Injector WCF Integration 包。 WCF 集成包的 2.3.0 版本修复了这个问题。

    第二种解决方案是根本不使用 Per WCF Operation,而是使用生命周期范围(其工作方式类似于 Per WCF Operation 生活方式)。在您的情况下,这是一个特别好的解决方案,因为您使用 command handlersquery handlers。换句话说,您的 WCF 服务可能会consist of just two WCF operations。这使得将这两个方法包装在生命周期范围内变得非常容易,而无需担心必须将代码添加到服务中的所有其他操作中(因为您的服务将不再获得任何操作)。您的操作将如下所示:

    [OperationContract]
    public object Execute(dynamic command)
    {
        Type commandHandlerType = typeof(ICommandHandler<>)
            .MakeGenericType(command.GetType());
    
        using (Bootstrapper.BeginLifetimeScope())
        {
            dynamic commandHandler = Bootstrapper.GetInstance(commandHandlerType);
    
            commandHandler.Handle(command);
        }
    
        return command;
    }
    

    当然,使用 Per WCF Operation 进行的所有注册都应更改为 Lifetime 范围:

    _container.Register<MyDbContext, MyDbContext>(new LifetimeScopeLifestyle());
    

    【讨论】:

    • 我在接下来的 sprint 中尝试第二个解决方案并等待更新。只需在两个服务中更改一个注册和两个方法。
    • 第二个解决方案是五分钟修复并运行。太好了,大力支持!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    相关资源
    最近更新 更多