【问题标题】:Am I using correct lifetime managers for dependency injection?我是否使用正确的生命周期管理器进行依赖注入?
【发布时间】:2016-03-03 15:45:43
【问题描述】:

我有一个 asp.net web api 应用程序,它使用来自 MS Unity.AspNet.WebApi 和 Unity nuget 包的 Unity 依赖注入库。此外,该应用程序为 ORM 和通用存储库使用实体框架版本 6 数据库上下文。

自定义服务类型由 Api 控制器使用。自定义服务类使用 EF 数据库上下文和通用存储库。

我的问题是: HierarchicalLifetimeManager 和 ContainerControlledLifetimeManager 是否适用于我的 Web api 应用程序的正确生命周期管理器?

我的应用程序的 UnityConfig 类中的代码:

    using System;
    using System.Configuration;
    using System.Data.Entity;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using App.Api.Models;
    using App.Dal;

    public class UnityConfig
        {
            #region Unity Container
            private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            });

            /// <summary>
            /// Gets the configured Unity container.
            /// </summary>
            public static IUnityContainer GetConfiguredContainer()
            {
                return container.Value;
            }
            #endregion

            /// <summary>Registers the type mappings with the Unity container.</summary>
            /// <param name="container">The unity container to configure.</param>
            /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
            /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
            public static void RegisterTypes(IUnityContainer container)
            {

                var connectionStringEntityFramework= ConfigurationManager.ConnectionStrings["AppEntities"].ToString();


            // Entity Framework database context and generic repository
// HierarchicalLifetimeManager  is used:

                container.RegisterType<DbContext, FirstAngularJsEntities>(new HierarchicalLifetimeManager(), new InjectionConstructor(connectionStringFirstAngularJsEntities));
                container.RegisterType<IRepository, GenRepository>(new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(DbContext)));


                // services
// ContainerControlledLifetimeManager is used:

                container.RegisterType<IContactService, ContactService>(new ContainerControlledLifetimeManager());
                container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());

            }

一个示例 api 控制器在其构造函数中注入了自定义服务:

public class ContactApiController : ApiController
    {
        private readonly IContactService _contactService;

        public ContactApiController(IContactService contactService)
        {
            _contactService = contactService;
        }

...
}

一个示例自定义服务在其构造函数中注入了 EF DbContext 和存储库:

public class ContactService : IContactService
    {
        private readonly IRepository _repo;
        private readonly DbContext _context;


        public ContactService(DbContext context, IRepository repo)
        {
            _context = context;
            _repo = repo;

        }

...
}

【问题讨论】:

    标签: asp.net-web-api dependency-injection inversion-of-control unity-container repository-pattern


    【解决方案1】:

    使用ContainerControlledLifetimeManager,您将获得单例服务。一个实例很长时间(直到 IIS 回收)。 HierarchicalLifetimeManager 与子容器一起使用 - 为每个子容器创建对象的新实例,因此您不必创建子容器,它再次像单例一样工作:) WebApi 应用的最佳方式是使用PerRequestLifetimeManager。 为对 Api 的每个请求创建新实例。

    【讨论】:

    • 感谢您的回复。所以 PerRequestLifetimeManager 用于 WebApi 应用程序。 ContainerControlledLifetimeManager 和 HierarchicalLifetimeManager 用于哪些类型的应用程序? 2 位终身经理是单身人士;可能会发生过时数据问题,对吗?
    • @Thomas.Benz ContainerControlledLifetimeManager 适用于长期存在的静态对象(从应用程序开始到结束)。 HierarchicalLifetimeManager 用于子容器。例如,当你运行某个子进程时,你可以创建一个子容器,这个进程会得到它自己的类实例
    • 很抱歉让您感到痛苦,但“最佳方式”可能取决于依赖项的要求,而不是说PerRequestLifetimeManager最适合所有WebAPI。在许多情况下,最好的方法是每次都创建一个单独的实例,而在其他情况下,最好的方法可能是使用单例。
    • @BenCr 我同意你的观点 :) “最好”这个词在这里并不是最好的。我认为,最好使用“最简单的”或“可能的解决方案之一”。你怎么看?
    • PerRequestLifetimeManagerUnity.Mvc 的一部分,当将 NUGET 包添加到 Web Api 项目时,它会引入其他 MVC (web ui) 相关的依赖项。由于许多原因,这不太理想。您能否建议如何使用 PerRequestLifetimeManager 或在 Web Api 中获得相同的行为,而不必引入这些不需要的其他程序集?
    【解决方案2】:

    我倾向于将此视为与您尝试执行的操作的语义兼容的最短生命周期,除非另有要求,否则默认生命周期为瞬态。

    1. DbContext 保持状态,因此我们需要对请求保持一致,因此 PerRequest 或 Hierachic
    2. 存储库是/应该是无状态的,因为它的状态是 DbContext,所以瞬态
    3. 服务是/应该是无状态的,所以是瞬态的

    使用 Hierarchic 而不是 PerRequest 的一个原因是 PerRequest 管理器不能很好地与 Owin 配合使用,请参阅 http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity,并且您需要编写一些清理中间件来替换 HttpModule

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 2017-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多