Search code examples
c#unity-container

Retrieve instantiated types from UnityContainer


(Using Unity 4.0.1)

Given a UnityContainer object, is there any way to retrieve all the objects that have been instantiated by the container up to that point in time? E.g. something like

IEnumerable<object> instantiatedObjects = unityContainer.GetAllInstantiatedObjects();

or, even better, filtering according to those that derive from a given type:

IEnumerable<IFoo> instantiatedFoos = unityContainer.GetAllInstantiatedObjects<IFoo>();


Solution

  • Following RB's suggestion, the following approach implements a custom Unity extension with a strategy that keeps a reference to each instantiated object upon PostInitializtion.

    N.B. The following code is for illustration only, and is not intended to be thread-safe/exception-safe etc.

    First, the implementation of the Extension class and other classes it relies on.

    public class ObjectContainer
    {
        private readonly List<object> _instantiatedObjects = new List<object>();
        public void Add(object instantiatedObject)
        {
            _instantiatedObjects.Add(instantiatedObject);
        }
        public IEnumerable<object> GetInstantiatedObjects()
        {
            return _instantiatedObjects;
        }
        public IEnumerable<T> GetInstantiatedObjects<T>()
        {
            return GetInstantiatedObjects().OfType<T>();
        }
    }
    
    public class InstantiatedObjectsStrategy : BuilderStrategy
    {
        private readonly ObjectContainer _objectContainer;
        public InstantiatedObjectsStrategy(ObjectContainer objectContainer)
        {
            _objectContainer = objectContainer;
        }
        public override void PostBuildUp(IBuilderContext context)
        {
            _objectContainer.Add(context.Existing);
        }
    }
    
    public class InstantiatedObjectsExtension : UnityContainerExtension
    {
        private readonly ObjectContainer _objectContainer = new ObjectContainer();
        protected override void Initialize()
        {
            Context.Container.RegisterInstance(_objectContainer);
            Context.Strategies.Add(new InstantiatedObjectsStrategy(_objectContainer),
                UnityBuildStage.PostInitialization);
        }
    }
    

    The extension can be added to the UnityContainer immediately after creation:

    IUnityContainer container = new UnityContainer();
    container.AddNewExtension<InstantiatedObjectsExtension>();
    

    The instantiated objects can then be retrieved from the container at a later stage as follows:

    IEnumerable<object> instantiatedObjects = container.Resolve<ObjectContainer>().GetInstantiatedObjects();
    IEnumerable<Foo> instantiatedFoos = container.Resolve<ObjectContainer>().GetInstantiatedObjects<Foo>();