我是否使用正确的生命周期管理器进行依赖注入?

Am I using correct lifetime managers for dependency injection?

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

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

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

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

    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;

        }

...
}

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

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

  1. DbContext 保持状态,因此我们需要对请求保持一致,以便 PerRequest 或 Hierachic
  2. Repository is/should 是无状态的,因为它的状态是 DbContext,所以 Transient
  3. 服务is/should是无状态的,所以是瞬态的

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