【问题标题】:ASP.NET MVC, Unity and IDisposableASP.NET MVC、Unity 和 IDisposable
【发布时间】:2014-02-19 21:59:42
【问题描述】:

我正在为 DI 使用 ASP.Net MVC 4、EF 和 Unity。也使用 UnitOfWork 模式。试图找出实现这一点的最佳方法。我有如下代码。 我遇到的问题是业务和存储库层中的 Dispose() 现在永远不会被调用,只有两者中的 Destructor 都会被调用,所以对象似乎永远不会被释放。 请回答以下问题

  1. 我真的需要业务和存储库层中的 IDisposable 实现吗(如果 Unity 已经在处理它)

  2. 我应该怎么做才能调用 Dispose()(我应该将它也添加到 Controller 并 Dispose 所有其他对象还是使用某些特定的 LifeTime 管理器)

  3. 我是应该使用每个实例的单例实例还是在每个请求中处理它,就像它在 Web 环境中一样。

Global.asax.cs:

private static IUnityContainer _unityContainer;

protected void Application_Start()
{
   _unityContainer = UnityBootstrapper.SetupUnity();
   _unityContainer.RegisterType<IController, ProductController>("Product");  
   DependencyResolver.SetResolver(new Microsoft.Practices.Unity.Mvc.UnityDependencyResolver(_unityContainer));
}  

UnityBootstrapper.cs:

public class UnityBootstrapper
{
    public static IUnityContainer SetupUnity()
    {
        UnityContainer container = new UnityContainer();
        container.RegisterType<IProductDbContext, ProductDbContext>()
                 .RegisterType<IUnitOfWork, UnitofWork>(new InjectionConstructor(new ResolvedParameter(typeof(IProductDbContext))))
                 .RegisterType<IProductRepository, ProductRepository>()
                 .RegisterType<IProductBusiness, ProductBusiness>();
    }
}

ProductController.cs:

public class ProductController : ControllerBase
{
    private readonly IProductBusiness _productBusiness;        

    public ProductController(IProductBusiness productBusiness)
    {
        _productBusiness = productBusiness;
    }

    //No Dispose for this
}

ProductBusiness.cs:

public class ProductBusiness : IProductBusiness, IDisposable
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly IProductRepository _productRepository;
    public ProductBusiness(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _productRepository = _unitOfWork.ProductRepository;
    }

    public override void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected override void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            if (disposing)
            {
                if (_productRepository != null) _productRepository.Dispose();
                if (_unitOfWork != null) _unitOfWork.Dispose();
            }

            _isDisposed = true;
         }
    }

    ~ProductBusiness()
    {
         Dispose(false);
    }
}

ProductRepository.cs:

public class ProductRepository : IProductRepository, IDisposable
{
    private readonly IProductDbContext _context;

    public ProductRepository(IProductDbContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        _context = context;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

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

            _isDisposed = true;
        }
    }

    ~ProductRepository()
    {
        Dispose(false);
    }
}   

【问题讨论】:

  • 感谢大家的及时回复
  • SA,欢迎来到 StackOverflow。按照这个社区的惯例,您通过投票回答来表示“谢谢”。然后将最有用的答案标记为已接受的答案。请查看有关投票的常见问题解答部分:stackoverflow.com/help/why-vote

标签: c# asp.net-mvc-4 dependency-injection unity-container idisposable


【解决方案1】:

您实际上并不需要处置对象,除非您在处置过程中做了特定的事情。 DI 容器会为您处理对象的生命周期。

有时 UoW 实施涉及保存处置时的更改。尽量避免这种情况。但如果这是不可避免的,您可以为此实现工厂:

public interface IUnitOfWorkFactory
{
    IUnitOfWork Create();
}

public class UnitOfWorkFactory : IUnitOfWorkFactory
{
    public IUnitOfWork Create()
    {
        return new UnitOfWork();
    }
}

public class UnitOfWork : IUnitOfWork, IDisposable
{
    // other implementation


    public void Dispose()
    {
        context.SaveChanges();
    }
}

然后消费者会做这样的事情:

public MyController(IUnitOfWorkFactory workFactory)
{
    this.workFactory = workFactory;
}

public ActionResult DoSomething()
{
    using(var uow = workFactory.Create())
    {
        //do work
    }
}

This DI book chapter 谈论一次性物品。

【讨论】:

    【解决方案2】:

    虽然 Unity will manage disposing of your registered 类型,您仍然必须在您的 IOC 容器上调用 dispose 以便它为它们执行此操作。

    从 Application_End 做,应该没问题。

        protected void Application_End()
        {
            _unityContainer .Dispose();
        }
    

    【讨论】:

      【解决方案3】:

      我相信,如果您设置了正确的 LifetimeManager,那么不,您不需要实现 IDisposable,因为统一会处理您的对象。这解释了不同类型的生命周期管理器http://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx

      我个人没有使用单例,只是让对象被创建然后在每个请求中处理。

      【讨论】:

        【解决方案4】:

        您实际上并不需要这些类上的 IDisposable,因为 IDisposable 的主要目的是清理非托管资源。看看这些:

        http://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx

        Proper use of the IDisposable interface

        如果您以服务位置方式使用容器,则对容器使用单例模式会很有帮助。但是,还有其他(可以说是更好的)方法来使用 Unity 或其他 DI/IoC 容器。那里有一些引导程序。例如:

        https://www.nuget.org/packages/Unity.Mvc/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-07
          相关资源
          最近更新 更多