Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. The project itself is an ASP.NET application that uses Web API.

I have the following packages installed.

  • Unity
  • Unity.ASPNet.WebAPI

I see no option to close/dispose the DBContext right after fetching the data.

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

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);
    }
}
like image 434
Karthikeyan Vijayakumar Avatar asked Dec 29 '17 15:12

Karthikeyan Vijayakumar


People also ask

Does Unity container Dispose objects?

Current implementation of UnityContainer does not implement a finalizer on the UnityContainer class. As result, when the container is discarded without calling IDisposable. Dispose() , all the container controlled objects are discarded as well, instead of properly disposing them.

How do you use the Dispose method?

The Dispose(bool) method overloadThe disposing parameter should be false when called from a finalizer, and true when called from the IDisposable. Dispose method. In other words, it is true when deterministically called and false when non-deterministically called.

How Dispose works c#?

In the context of C#, dispose is an object method invoked to execute code required for memory cleanup and release and reset unmanaged resources, such as file handles and database connections.


1 Answers

First you might want to add one more Unity bootstrapper to your project Unity.AspNet.Mvc

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.

Unity.Mvc and Unity.AspNet.WebApi will register your controllers for DI.

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...

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...

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.

I have an example here https://github.com/jasenhk/MovieStar

If you are using OWIN see Unity IoC does not inject dependency into Web API Controller

like image 53
Jasen Avatar answered Nov 06 '22 09:11

Jasen