hetnet
hetnet

Reputation: 301

Disposing needed in Unity?

Probably a Unity beginner's question: when using Unity, would you still need to implement Dispose methods on the objects you have injected? Or is even this not needed (so, done automatically by Unity)? This is in the context of a web application.

Upvotes: 30

Views: 30672

Answers (3)

Brains
Brains

Reputation: 664

Another lifetime manager ContainerControlledTransientManager that respects IDisposable was added to Unity on Jan 11, 2018 Add container 'owned' transient lifetime manager ContainerControlledTransientManager #37

So, ContainerControlledTransientManager is required. This lifetime manager is the same as TransientLifetimeManager except if the object implements IDisposable it will keep strong reference to object and dispose it when container is disposed. If created object is not disposable, container does not maintain any object references so when that object is released GC will collect it immediately.

Upvotes: 0

Jehof
Jehof

Reputation: 35544

Implementing IDisposable has nothing to do with Unity. You should implement the interface when your type is using unmanaged resources likes Files, that cannot be garbage collected by the CLR.

Unity can manage the lifetime of your types and instances. For this case Unity provides diffrent types of LifeTimeManager to control the lifetime of your instances.

Unity does only respect the IDisposable interface when you register them using the ContainerControlledLifetimeManager or the HierarchicalLifetimeManager. That meens when you dispose the Unity-Container it will also call Dispose on all instances implementing the IDisposable interface registered by the named LifetimeManager above.

When you register types that implement the IDisposable interface using the TransientLifetimeManager (you get a new instances each type you call Resolve on the container), it is up to you to call Dispose on the instance.

Upvotes: 34

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

To extend on what Jehof said, ContainerControlledLifetimeManager and HierarchicalLifetimeManager both will call .Dispose() on the class if it supports it. However, a interesting fact is only the concrete implementation needs to implement IDisposable, the interface you are mapping does not. Here is a simple example program to demonstrate.

using System;
using System.Threading;
using Microsoft.Practices.Unity;

namespace ConsoleApplication
{
    internal class Program
    {
        private interface IFoo
        {
        }

        private class Foo : IFoo, IDisposable
        {
            public Foo()
            {
                Console.WriteLine("Foo Created");
            }

            public void Dispose()
            {
                Console.WriteLine("Foo.Dispose() called");
            }
        }

        private class Bar
        {
            public Bar(IFoo foo)
            {
            }
        }

        private static void Main()
        {
            LifetimeManager manager;

            Console.WriteLine("Choose a lifetime manager to test:");
            Console.WriteLine(" 1: ContainerControlledLifetimeManager");
            Console.WriteLine(" 2: ExternallyControlledLifetimeManager");
            Console.WriteLine(" 3: HierarchicalLifetimeManager");
            Console.WriteLine(" 4: PerThreadLifetimeManager");
            Console.WriteLine(" 5: TransientLifetimeManager");

            int choice = int.Parse(Console.ReadLine());
            switch (choice)
            {
                case 1:
                    manager = new ContainerControlledLifetimeManager();
                    break;
                case 2:
                    manager = new ExternallyControlledLifetimeManager();
                    break;
                case 3:
                    manager = new HierarchicalLifetimeManager();
                    break;
                case 4:
                    manager = new PerThreadLifetimeManager();
                    break;
                case 5:
                    manager = new TransientLifetimeManager();
                    break;
                default:
                    return;
            }

            Console.WriteLine(manager.ToString());

            //Use a thread to test PerThreadLifetimeManager's Dispose actions.
            var thread = new Thread(() => PerformTest(manager));
            thread.Start();
            thread.Join();


            Console.WriteLine("Press enter to exit...");
            Console.ReadLine();
        }

        private static void PerformTest(LifetimeManager manager)
        {
            Console.WriteLine("Pre container creation");
            using (IUnityContainer container = new UnityContainer())
            {
                Console.WriteLine("Pre type regrestration");
                container.RegisterType<IFoo, Foo>(manager);

                Console.WriteLine("Pre bar1 resolve");
                var bar1 = container.Resolve<Bar>();

                Console.WriteLine("Pre bar2 resolve");
                var bar2 = container.Resolve<Bar>();

                Console.WriteLine("Leaving container scope.");
            }
        }
    }
}

Upvotes: 9

Related Questions