Dependency injection when using abstract base class

JasinCole

Well-known member
Joined
Feb 16, 2023
Messages
66
Programming Experience
1-3
How do you handle DI when using abstract base class?

C#:
public abstract class Base
{
    protected Object obj;
    
    protected Base(Object obj)
    {
        Obj = obj;
    }
}

It seems I must do this
C#:
public class ClassA
{
    public ClassA(Object obj) : base(obj)
    {
        
    }
}

But at this point why do I need a base class if every other class is passing along the dependency?
 
You need a base class when there is a common object type that all your specialized concrete classes share. The fact that the base class needs somethings to initialize it indicates that all the concrete classes either also need those things (or can provide those things to the base class somehow).
 
How do you handle DI when using abstract base class?

Your question is nearly so abstract it's hard to answer (give a sensible example?) but in essence it's "the same way you would if you were injecting dependencies yourself" - just because it's software injecting dependencies instead of you doesn't chnge much; you still have to deciie what dependencies it injects, just like you would if you were doing the injecting by passing some class you'd recently new'd or got from a cache etc/whatever

IoC containers work to simple rules.. "when you see a need for type X, inject your instance of type Y". You can't have an instance of an abstract class you could inject yourself, so you can't get an IoCC to DI one either. You have a concrete subclass that you can make, and I guess in your case you'd tell the IoCC "when you see a requirement for Base, inject a ClassA*"



* just don't get seen by the cops
 
My base class has a common property that all super classes need to work. I just find it odd that my super class is doing the DI and then passing that to the base class(Can't the base class get it's own dependency?? just like the super class is capable of?? and assign it to the common property??).

At this point I am wondering why am I needing the base class to hold the common property? I could just use the super class(as a normal class, no inheritence) and create a field from the dependency I injected, assign the field and use it. the extra 2 lines of code is minimal and would also keep the code of the super class more self contained.

It doesn't feel like I am saving myself any effort by using the base class. Which is the crux of the issue in my mind. I tend to only like to do something when it feels efficient, worthwhile.
 
You use a base class when you want to treat a host of derived classes as if they were a base; they have an intrinsic is-a relationship. You don't use them just because you have 10 classes that all need a StringBuilder; that's a has-a relationship.

At this point I am wondering why am I needing the base class to hold the common property?
You don't; you can have 10 normal classes that take a Foo in their constructor, and have the injector inject the same instance if you want. You have 100 classes that all have a ILogger instance injected; the classes are not related in any way and it makes no sense to derive them all from CanHazLogger, nor to have them implement ICanHazLogger unless you really do want to have an array of all of them that you enumerate, calling the same method on every one of the 100

My base class has a common property that all super classes need

Be careful with your terminology; base classes are super classes; super is a Java thing, base is a C# thing. Base classes have derived (sub/child) classes
 
Last edited:
The reason for the base class is because some other code is requiring it that I did not write. Since that base class was empty and I had to use it, I figured I'd use it to declare and assign some common properties that all super classes used. Thinking the base class should be capable of using DI to get the object.
 
assign some common properties that all super classes used

Stop calling them super classes when you mean subclasses; you're going to confuse every developer you talk to

I figured I'd use it

OK, so the injector will inject IFooA, IFooB and IFooC into your derived class constructor, and that derived constructor will call base(fooA, fooB, fooC). What is the complaint? That you have to write base(..) all the time?

You want the injector to see that your base has IFooA IFooB and IFooC properties and populate them without you having to proxy it? Are they truly optional? (The way you've talked about them so far is that they're required for these classes to work, whereas the rule of thumb for property injection (which .net DI doesn't always do) is that they're optional dependencies, unlike constructor injected attributes that are mandatory for the class to function)
 
Last edited:
I agree I am probably confusing myself.

But when using constructor injection you don't have to pass in the dependency. One point of IoC, right?
on that assumption, base (dependency) seems silly.
 
Okay... Follow through with that logic. Since an IoC is not built into the C# language, how will the dependency be fulfilled without explicitly passing it along?
 
when using constructor injection you don't have to pass in the dependency

When using any kind of IoC you yourself don't have to pass in the dependency, you tell the IoC what to pass and how to create it (how to manage the lifecycle of what it creates) and it passes it for you.. But you still had to configure it to know wha to pass, so the impetus still comes from you

You tell your IoC e.g.:

When you see IFooA, pass a the same instance of FooA you created at the start of time (Singleton)
When you see IFooB, pass a the same instance of FooB you created at the start of the current http request (Scoped)
When you see IFooC, pass a new instance of FooC (Transient)

Supposing you have Base, whose constructor takes an IFooA, IFooB and IFooC, and you also have a Bar, which is a derivative of Base and also has a similarly patterned constructor, and you've told the IoC that Bar is transient (say), and you've got ControllerX whose constructor demands a Bar..

The IoC will start satisfying the Bar demand for ControllerX; it makes a Bar, and it passes the FooA from the dawn of time, the FooB it made when the request came in and a new FooC. It doesn't look at Bar and go "oh, it's derived from Base, which also takes an IFooA, IFooB and IFooC.. I'll just call the base constructor.." because it can't. It's new()ing a Bar, and C# is running the constructor - the IoC can only feed into Bar's constructor. If Bar wants Base to have the same FooX, it has to do the proxying to Base in its own (Bar) constructor. This might be different if you were using property injection, and the injector could see that Bar is a base and a Base has 3 props that it has to inject for..

But right now we seem to be discussing the merits and options for attempting (impossibly) to get rid of a single line of code that calls base(x,y,z)
 
Last edited:
Or it possible the OP was trained by an 80's (or early 90's) teacher when it used to be touted that the primary use of inheritance is cut down on the amount of code written. We have learned since then that inheritance is a way to share behavior and that cutting down on the amount of code in incidental. We have also learned since then to prefer aggregation over inheritance, due to the fragile nature of inheritance.
 

Latest posts

Back
Top Bottom