ASP.NET MVC、Unity和IDisposable

8
我正在使用ASP.NET MVC 4,EF和Unity进行DI。同时使用了UnitOfWork模式。我试图找出最佳实现方式。我的代码如下。
我遇到的问题是业务层和存储库层中的Dispose()从未被调用,只有析构函数被调用,因此对象似乎从未被处理。
请回答以下问题:
1.如果Unity已经将其照顾好了,那么我是否真的需要在业务和存储库层中实现IDisposable接口?
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);
    }
}   

感谢大家的迅速回复。 - SRAMPI
SA,欢迎来到StackOverflow。在这个社区中,按照惯例,您可以通过给答案点赞来表示“谢谢”。然后选择最有用的答案作为被采纳的答案。请查看关于点赞的FAQ部分:http://stackoverflow.com/help/why-vote - trailmax
4个回答

3

除非在处理过程中有特定需求,否则您不需要手动释放对象。依赖注入容器会为您管理对象的生命周期。

有时候工作单元(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
    }
}

这本DI书的这个章节讲述了可释放对象。


1

尽管Unity 将管理您注册的 类型,但您仍然需要调用IOC容器上的dispose方法,以便它为它们处理。

从Application_End中执行此操作应该没问题。

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

1
我相信如果您设置了正确的LifetimeManager,那么不需要实现IDisposable,因为Unity会处理对象的释放。这个链接解释了不同类型的Lifetime Manager http://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx
个人而言,我没有使用单例模式,而是让对象在每个请求中创建和释放。

0

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

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

IDisposable接口的正确使用

如果您以服务定位方式使用容器,则使用单例模式可以很有帮助。但是,使用Unity或其他DI / IoC容器的其他(并且可以说更好的)方法也存在。有一些引导程序可供选择。例如:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接