完成请求后,如何处置由Unity DI创建的对象?

Kar*_*mar 5 c# asp.net entity-framework unity-container asp.net-web-api

我想知道是否有更好的方法来处理此问题。

我已经为我们的项目设置了Unity以进行依赖项注入。该项目本身是使用Web API的ASP.NET应用程序。

我安装了以下软件包。

  • 统一
  • Unity.ASPNet.WebAPI

我看不到在获取数据后立即关闭/处置DBContext的选项。

我的控制器

public class NinjasController : ApiController
{
    public Ninja Get(int id)
    {
        INinjaRepository repository = UnityConfig.Container.Resolve(typeof(INinjaRepository), null) as INinjaRepository;
        Ninja ninja = repository.GetNinjaById(id);
        repository.CanBeDisposed = true;
        repository = null;
        UnityConfig.PerRequestLifetimeManager.Dispose();
        return ninja;
    }
}
Run Code Online (Sandbox Code Playgroud)

UnityConfig

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

    public static IUnityContainer Container => container.Value;
    public static PerRequestLifetimeManager PerRequestLifetimeManager;

    public static void RegisterTypes(IUnityContainer container)
    {
        PerRequestLifetimeManager = new PerRequestLifetimeManager();
        container.RegisterType<INinjaRepository, NinjaRepository>(PerRequestLifetimeManager);
    }
}
Run Code Online (Sandbox Code Playgroud)

终身经理

public class PerRequestLifetimeManager : TransientLifetimeManager, IDisposable
{
    private static List<IBaseRepository> list = new List<IBaseRepository>();

    public override void SetValue(object newValue, ILifetimeContainer container = null)
    {
        base.SetValue(newValue, container);

        IBaseRepository disposable = newValue as IBaseRepository;
        if (disposable != null)
            list.Add(disposable);
    }

    public void Dispose()
    {
        foreach (IBaseRepository item in list.FindAll(item => item.CanBeDisposed))
        {
            if (item != null)
            {
                try
                {
                    item.Dispose();
                }
                catch (Exception)
                {
                    // log exception and continue
                }
            }
        }

        list.RemoveAll(item => item.CanBeDisposed);
    }
}
Run Code Online (Sandbox Code Playgroud)

资料库

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    internal DbContext _context;
    internal DbSet<TEntity> _dbSet;
    public bool CanBeDisposed { get; set; }

    public GenericRepository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    protected void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

Jas*_*sen 6

首先,您可能想要向项目Unity.AspNet.Mvc中添加另一个Unity引导程序。

https://msdn.microsoft.com/zh-CN/library/dn507440(v=pandp.30).aspx

要在ASP.NET Web API应用程序中使用PerRequestLifetimeManager类,还必须将ASP.NET MVC NuGet程序的Unity Bootstrapper添加到项目中。

Unity.Mvc和Unity.AspNet.WebApi将为DI注册您的控制器。

UnityConfig.cs

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<INinjaContext, NinjaContext>(new PerRequestLifetimeManager());
    container.RegisterType<INinjaRepository, NinjaRepository>(new PerRequestLifetimeManager());
}
Run Code Online (Sandbox Code Playgroud)

UnityWebApiActivator.cs取消注释行...

public static void Start()
{
    // Use UnityHierarchicalDependencyResolver if you want to use
    // a new child container for each IHttpController resolution.
    var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);

    ...
}
Run Code Online (Sandbox Code Playgroud)

UnityMvcActivator.cs取消注释行...

public static void Start()
{
    ...

    // TODO: Uncomment if you want to use PerRequestLifetimeManager
    Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
Run Code Online (Sandbox Code Playgroud)

您的控制器就是

public class NinjasController : ApiController
{
    private readonly INinjaRepository repository;

    public NinjasController(INinjaRepository repository)
    {
        this.repository = repository;
    }

    public Ninja Get(int id)
    {
        var ninja = repository.GetNinjaById(id);
        return ninja;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用PerRequestLifetimeManager,在请求完成后,Unity将负责处理。

我在这里有一个例子https://github.com/jasenhk/MovieStar

如果您使用的是OWIN,请参见Unity IoC不会将依赖项注入Web API控制器