Provide "Dependor" Type Information to "Dependee" During Resolve

Mar 18, 2013 at 10:11 PM
Is there an extension method on the Unity container that can provide this information? Presumably it would be used by an InjectionFactory.

This SO question explains the rationale and example syntax.
Editor
Mar 19, 2013 at 3:00 AM
The article Log4Net Integration with Unity IoC Container shows how to something very similar using Log4Net. It uses StackFrame to determine the class name.

You could also implement that yourself without StackFrame. Here is a naive approach that has not been fully tested (in other words, there are probably some issues with this!) but it's the start of an approach.

So for our example we first define a logger:
    public interface ILogger
    {
        void Write(string message);
    }

    public class ConsoleLogger : ILogger
    {
        private string className;

        public ConsoleLogger(string className)
        {
            this.className = className;
        }

        public void Write(string message)
        {
            Console.WriteLine(message);
        }
    }
Then we define some classes that use the ILogger:
    public class Helper
    {
        private ILogger logger;

        public Helper(ILogger logger)
        {
            this.logger = logger;
        }
    }

    public class Processor
    {
        private ILogger logger;
        private Helper helper;

        public Processor(ILogger logger, Helper helper)
        {
            this.logger = logger;
            this.helper = helper;
        }
    }

    public class Processor2
    {
        private ILogger logger;

        public Processor2(ILogger logger)
        {
            this.logger = logger;
        }
    }

    public class Processor3
    {
        public Processor3()
        {
        }
    }
Next we create a container extension and an IBuilderPolicy:
    public class LoggerResolverOverrideExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            var strategy = new MyBuilderStrategy(Container);

            Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
        }

        class MyBuilderStrategy : BuilderStrategy
        {
            private readonly IUnityContainer container;

            public MyBuilderStrategy(IUnityContainer container)
            {
                this.container = container;
            }

            public override void PreBuildUp(IBuilderContext context)
            {
                LoggerBuildPolicy loggerPolicy = null;
                
                if (typeof(ILogger).IsAssignableFrom(context.BuildKey.Type))
                {
                    string injectName = "";

                    loggerPolicy = context.Policies.Get<LoggerBuildPolicy>("");

                    if (loggerPolicy != null)
                    {
                        injectName = loggerPolicy.GetObjectName();
                    }

                    context.AddResolverOverrides(new ParameterOverride("className", injectName));
                }
                else
                {
                    loggerPolicy = context.Policies.Get<LoggerBuildPolicy>("");

                    if (loggerPolicy == null)
                    {
                        loggerPolicy = new LoggerBuildPolicy();
                        context.Policies.Set<LoggerBuildPolicy>(loggerPolicy, "");
                    }

                    loggerPolicy.AddObjectName(context.BuildKey.Type.Name);
                }
            }
        }
    }

    public class LoggerBuildPolicy : IBuilderPolicy
    {
        private Stack<string> hierarchy = new Stack<string>();

        public LoggerBuildPolicy()
        {
        }

        public void AddObjectName(string name)
        {
            hierarchy.Push(name);
        }

        public string GetObjectName()
        {
            return hierarchy.Peek();
        }
    }
Then we register the extension, the logger and resolve our processors:
    IUnityContainer container = new UnityContainer();
    container.AddNewExtension<LoggerResolverOverrideExtension>();

    container.RegisterType<ILogger, ConsoleLogger>();

    var processor = container.Resolve<Processor>();
    var processor2 = container.Resolve<Processor2>();
    var processor3 = container.Resolve<Processor3>();
    logger = container.Resolve<ILogger>();
Hope that helps.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to