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

问题描述 投票:4回答:1

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

我为我们的项目设置了Unity for dependency injection。项目本身是一个使用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;
    }
}

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

终身经理

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

知识库

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);
    }
}
c# asp.net entity-framework asp.net-web-api unity-container
1个回答
5
投票

首先,您可能希望在项目Unity.AspNet.Mvc中再添加一个Unity引导程序

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

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

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

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取消注释行...

public static void Start()
{
    ...

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

你的控制器很简单

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

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

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

如果您正在使用OWIN,请参阅Unity IoC does not inject dependency into Web API Controller

© www.soinside.com 2019 - 2024. All rights reserved.