我是否使用正确的生命周期管理器进行依赖注入?
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。
- DbContext 保持状态,因此我们需要对请求保持一致,以便 PerRequest 或 Hierachic
- Repository is/should 是无状态的,因为它的状态是 DbContext,所以 Transient
- 服务is/should是无状态的,所以是瞬态的
使用 Hierarchic 而不是 PerRequest 的一个原因是 PerRequest 管理器不能很好地与 Owin 配合使用,请参阅 http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity,您将需要编写一些清理中间件来替换 HttpModule
我有一个 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。
- DbContext 保持状态,因此我们需要对请求保持一致,以便 PerRequest 或 Hierachic
- Repository is/should 是无状态的,因为它的状态是 DbContext,所以 Transient
- 服务is/should是无状态的,所以是瞬态的
使用 Hierarchic 而不是 PerRequest 的一个原因是 PerRequest 管理器不能很好地与 Owin 配合使用,请参阅 http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity,您将需要编写一些清理中间件来替换 HttpModule