我是否使用正确的终身经理进行依赖注入?

时间:2016-03-03 15:45:44

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

我有一个asp.net web api应用程序,它使用来自MS Unity.AspNet.WebApi和Unity nuget包的Unity依赖注入库。此外,该应用程序使用ORM的Entity Framework版本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;

        }

...
}

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

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

  1. DbContext保持状态,因此我们需要对请求保持一致,以便PerRequest或Hierachic
  2. 存储库是/应该是无状态的,因为它的状态是DbContext,所以Transient
  3. 服务是/应该是无国籍的,所以Transient
  4. 使用Hierarchic而不是PerRequest的一个原因是PerRequest管理器与Owin不兼容,请参阅http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity,您需要编写一些清理中间件来替换HttpModule