如何结合 WCF 和 Web 的 SimpleInjector API

How to combine SimpleInjector for WCF and Web API

我有一个托管 WCF 和 Web API V2 ApiControllers 的 Web 项目。

两者都应该从使用 SimpleInjector 中获益。

这 2 种技术有 2 种不同的 nuget 包:

在给定的案例中,两者的注册应该相同,解决这个问题的最佳方法是什么? 我是否应该创建 2 个不同的容器,因为只要请求打开,范围就会一直有效?

我目前实现了以下,以使用正确的 ScopedLifestyles:

    public static void ConfigureForWCF(Container container)
    {
        container.Options.DefaultScopedLifestyle = new WcfOperationLifestyle();

        RegisterImplementations(container);
    }

    public static void ConfigureForWebAPI(Container container)
    {
        container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

        RegisterImplementations(container);
    }

    public static void RegisterImplementations(Container container)
    {
        // registrations for both WCF and Web API in here
        container.Register<IMyInterface, MyClass>();

我知道这样称呼他们:

        // container for WCF
        var containerWCF = new Container();

        SimpleInjectorConfiguration.ConfigureForWCF(containerWCF);

        containerWCF.Verify();

        // use the container for WCF
        SimpleInjectorServiceHostFactory.SetContainer(containerWCF);



        // container for Web API
        var containerWebAPI = new Container();

        SimpleInjectorConfiguration.ConfigureForWebAPI(containerWebAPI);

        // this doesn't currently make sense for me as the controllers inheriting from ApiController get registered as Transient 
        //containerWebAPI.RegisterWebApiControllers(GlobalConfiguration.Configuration);
        // instead I will register the Controllers manually

        containerWebAPI.Verify();

        // use the container for Web API
        GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(containerWebAPI);

最后能不能用同一个Container? (在两个容器上调用 Verify 也没有意义,只要它们具有相同的注册)

你基本上有 3 个选择:

  1. 使用两个容器实例
  2. 使用一个包含 hybrid lifestyle 的容器实例,混合 WebApiRequestLifestyleWcfOperationLifestyle
  3. 对 WCF 和 Web 使用一个容器并使用相同的生活方式 API。这通常是 AsyncScopedLifestyle.

是否可以拥有两个容器取决于多个值,例如在整个 AppDomain 中应该恰好存在一次的服务数量。当您有 2 个容器实例时,每个实例都有自己的单例实例,因此您应该为每个容器提供一个现有实例。这可能会很麻烦,但在大多数情况下,容器获取自己的单例实例应该不是问题。

另一方面,拥有 2 个容器意味着您必须使用一些共享逻辑来填充两个容器实例共享的注册。这会使事情复杂化。

另一方面,拥有两个容器是否允许两个服务以隔离的方式运行,这可能是有益的。

如果您选择拥有一个容器实例,那么使用混合生活方式将是最明显的解决方案,特别是因为 WCF 使用的范围技术不同于(基于 ThreadScopedLifestyle)Web API 作用域技术(基于 AsyncScopedLifestyle)。因此,最简单的解决方案是将它们注册为混合体,如下所示:

container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
    defaultLifestyle: new WebApiRequestLifestyle(),
    fallbackLifestyle: new WcfOperationLifestyle());

使用此配置,Simple Injector 将在存在活动 Web API 作用域(这意味着 AsyncScopedLifestyle 作用域)时使用 WebApiRequestLifestyle。如果没有这样的范围,它将回退到使用 WcfOperationLifestyle.

如果您希望拥有一个容器,这将是最简单的解决方案。

最后一个选项是对 WCF 和 Web API 应用程序使用一种特定范围的生活方式。由于 Web API 本质上是异步的,唯一明显的生活方式是 AsyncScopedLifestyle。使用 ASP.NET Core,我们实际上正在摆脱自定义框架特定的生活方式,而是主要使用 AsyncScopedLifestyle

尽管您可以在 Web API 应用程序中交替使用 AsyncScopedLifestyleWebApiLifestyle,但这不适用于 WCF。这是因为 WCF 集成包使用了一种类似于 ThreadScopedLifestyle 的技术,但使用了它自己的实现。

尽管您也可以在单线程应用程序上使用 AsyncScopedLifestyle,但您必须替换当前启动 WCF 作用域的 WCF 基础结构的一部分,以使其启动异步作用域。

由于要做的工作有点多,我会选择使用 2 个容器,或者使用混合生活方式。