简体   繁体   English

如何在完成请求后立即处理Unity DI创建的对象?

[英]How to dispose the object created by Unity DI right after the completing the request?

I want to know if there is a better to way to handle this. 我想知道是否有更好的方法来处理这个问题。

I've set up Unity for dependency injection for our project. 我为我们的项目设置了Unity for dependency injection。 The project itself is an ASP.NET application that uses Web API. 项目本身是一个使用Web API的ASP.NET应用程序。

I have the following packages installed. 我安装了以下软件包。

  • Unity 统一
  • Unity.ASPNet.WebAPI Unity.ASPNet.WebAPI

I see no option to close/dispose the DBContext right after fetching the data. 我看不到在获取数据后立即关闭/处理DBContext的选项。

My controller 我的控制器

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;
    }
}

UnityConfig 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);
    }
}

Lifetime Manager 终身经理

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);
    }
}

Repository 知识库

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);
    }
}

First you might want to add one more Unity bootstrapper to your project Unity.AspNet.Mvc 首先,您可能希望在项目Unity.AspNet.Mvc中再添加一个Unity引导程序

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

To use the PerRequestLifetimeManager class in an ASP.NET Web API application, you must also add the the Unity bootstrapper for ASP.NET MVC NuGet package to your project. 要在ASP.NET Web API应用程序中使用PerRequestLifetimeManager类,还必须将ASP.NET MVC NuGet包的Unity引导程序添加到项目中。

Unity.Mvc and Unity.AspNet.WebApi will register your controllers for DI. Unity.Mvc和Unity.AspNet.WebApi将为DI注册您的控制器。

UnityConfig.cs UnityConfig.cs

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

UnityWebApiActivator.cs Uncomment the line... 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);

    ...
}

UnityMvcActivator.cs Uncomment the line... UnityMvcActivator.cs取消注释行...

public static void Start()
{
    ...

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

Your controller is simply 你的控制器很简单

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;
    }
}

With PerRequestLifetimeManager Unity will take care of disposal after the request is complete. 使用PerRequestLifetimeManager Unity将在请求完成后负责处理。

I have an example here https://github.com/jasenhk/MovieStar 我在这里有一个例子https://github.com/jasenhk/MovieStar

If you are using OWIN see Unity IoC does not inject dependency into Web API Controller 如果您使用的是OWIN,请参阅Unity IoC不会将依赖注入Web API Controller

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM