Halvard
Halvard

Reputation: 4003

Dependency Injection, inheritance and generics

I am using dependency injection and have come up against something I can't figure out. I have a base class that needs a generic logger:

public class BaseClass
{
    public BaseClass(ILogger<BaseClass> logger)
    {
        // code here
    }
}

Then I have a class inheriting that also needs the generic logger:

public class SubClass : BaseClass
{
    public SubClass(ILogger<SubClass> logger)
    {
        // code here
    }
}

The problem is that this does not compile with the message; BaseClass does not contain a constructor that takes 0 arguments.

This would be easy to solve if I could do this:

public SubClass(ILogger<SubClass> logger) : base(logger)

The problem is that this is not legal either since ILogger<SubClass> is not an instance of ILogger<BaseClass> (it does not compile with The best overloaded match for ... has some invalid arguments).

One possible solution: I guess I do not have to use constructor injection and instead use the DependencyResolver.

The question: Surely someone else have come up against this issue before? Is it possible to do with constructor injection? If so, what should I do?

Note: In the current project I am using StructureMap (for MVC4), but I think that the tool here is slightly irrelevant.

Upvotes: 1

Views: 787

Answers (3)

gehho
gehho

Reputation: 9238

You could add a parameterless constructor in your BaseClass which would call the parameterized constructor and pass it a manually resolved ILogger instance. Something like this:

public BaseClass()
    : this(ResolveLogger())
{
}

private static ILogger<BaseClass> ResolveLogger()
{
    // resolve the instance manually and return it
}

This way, if an instance of type BaseClass is resolved, it would use the parameterized constructor and inject a resolved ILogger<BaseClass> instance. But if a derived class is resolved, this derived class would call the parameterless BaseClass() constructor and the ILogger<BaseClass> would be resolved manually.

Upvotes: 1

Gary W
Gary W

Reputation: 1904

Could you change the logger interface to be :

interface ILogger<out T> where T : BaseClass

Upvotes: 2

Alexey Solonets
Alexey Solonets

Reputation: 817

This happens because ILogger<SubClass> is not a subclass of ILogger<BaseClass> so compiler think that you wrote a new constructor. This is implicitly equivalent if you wrote

public class SubClass : BaseClass
{
    public SubClass(ILogger<SubClass> logger)
        : base() // since base class does not have a constructor 
                 // with no arguments, you will get the error
    {
        // code here
    }
}

So your question is not about dependency injection exactly. It is more about your architecture.

Upvotes: 1

Related Questions