Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Injector: Registering a type with constructor argument that's based on its parent

I am currently in the process of removing Ninject from my project, and moving to using Simple Injector but there is one thing that I can not get working properly.

For my logging, in the registering of services, I was previously able to pass in a parameter into my logging class as such

_kernel.Bind<ILogger>().To<Logger>()
    .WithConstructorArgument("name",
        x => x.Request.ParentContext.Request.Service.FullName);

I am looking for a way to recreate this in Simple Injector. So far I have everything else working but this. I can get the logging to work, albeit without having the correct logger names being shown, by doing the following:

_container.Register<ILogger>(() => new Logger("test"));

Anyone got any experience in doing anything similar?

like image 616
Thewads Avatar asked Dec 17 '12 15:12

Thewads


2 Answers

That registration is a form of context based injection. You can use one of the RegisterConditional overloads for this.

RegisterConditional however does not allow the use of factory methods to construct a type. So you should create a generic version of your Logger class, as follows:

public class Logger<T> : Logger
{
    public Logger() : base(typeof(T).FullName) { }
}

You can register it as follows:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Transient,
    c => true);

But please do read this Stackoverflow question (and my answer) and question yourself if you aren't logging too much.

like image 131
Steven Avatar answered Sep 22 '22 20:09

Steven


Context based injection is now supported in Simple Injector 3 by using the RegisterConditional method. For example to inject a Logger into Consumer1 and a Logger into Consumer2, use the RegisterConditional overload that accepts a implementation type factory delegate as follows:

container.RegisterConditional(
    typeof(ILogger),
    c => typeof(Logger<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Transient,
    c => true);
like image 33
Timothy Schoonover Avatar answered Sep 22 '22 20:09

Timothy Schoonover