1

I am trying to implement an abstract class using C#, that also combined Dependency Injection in the constructor. The approach I am currently taking seems rather cumbersome, and possibly wrong (!) so your help is greatly appreciated. This is the approach I have took:

public abstract class MyAbstractClass
{
    protected IValue Value { get; set; }

    public MyAbstractClass (IValue value) 
    {
        this.Value = value;
    }

    public abstract void Configuration();

    public void Confirmation()
    {
        // Do something
    }
}

public class MyMainClass : MyAbstractClass
{
    public MyMainClass (IValue value) : base (value)
    {
    }

    public override void Configuration()
    {
        // Configure
    }
}

// Calling MyMainClass from any method, which also has access to DI fields
public class AnotherClass()
{
    public IValue Value { get; set; }

    public AnotherClass(IValue value)
    {
        this.Value = value;
    }
    
    public void Worker()
    {
        var mainClass = new MyMainClass(Value);
    }
}

Now the problem lies in the Worker() with the class to MyMainClass(), since it seems like I am passing in a parameter, rather than utilising DI...

Thanks!

Chris
  • 11
  • 3
  • Why are you newing `MyMainClass`? Shouldn't the container be injecting that class with all dependencies satisfied? E.g. add `MyMainClass` as a constructor parameter to `AnotherClass`? – Charleh Aug 04 '21 at 11:02
  • Ah, that's a good point @Charleh, can you clarify what you mean by "add MyMainClass as a constructor parameter to AnotherClass" ? – Chris Aug 04 '21 at 11:04
  • `public AnotherClass(MyMainClass mainClass)`, it depends what `IValue` is though but my assumption is that you only need it to provide it as a parameter to `MyMainClass` which if you are injecting will automatically get its dependencies satisfied (assuming your container is setup correctly). I.e. if you have a dependency that has a sub dependency you don't need to provide those yourself, just ask for the dependency and the container will automatically resolve sub dependencies. – Charleh Aug 04 '21 at 11:08
  • I think that would tightly couple AnotherClass to MyMainClass, since I may also want to have MyMainClass2, MyMainClass3, all inheriting from AnotherClass. – Chris Aug 04 '21 at 11:11
  • If you are unsure, read this answer I posted many moons ago https://stackoverflow.com/questions/29890223/static-class-to-dependency-injection/29892572#29892572 – Charleh Aug 04 '21 at 11:11
  • If you don't want any coupling the only sure fire way to do that is via an interface. You are depending on concrete classes and therefore there will be some level of coupling. – Charleh Aug 04 '21 at 11:12
  • Let's just put it this way, the worst thing you can do is `new MyMainClass`, better is injecting `MyMainClass` and even better is injecting an interface `IMainClassThing` and choosing what implementation satisfies this interface at container configuration time or via a factory or something like that. – Charleh Aug 04 '21 at 11:15
  • Also, just re-read your comment and you are suggesting that you want to inherit from `AnotherClass`, but none of your current types inherit from it? Have you got an example of what you mean, or maybe some sort of use case which might help anyone looking at the question understand what your concept is? The more information about the context the better the answers you will get. – Charleh Aug 04 '21 at 11:18
  • Yeah for instance, Configuration is marked as abstract within MyAbstract class, and it's overridden in MyMainClass. – Chris Aug 04 '21 at 11:36

2 Answers2

0

What you need is a DI framework that creates factories for you and injects them into constructors. Autofac does this and is very well battle hardened.

Then you can do something like:

public class AnotherClass()
{
    private readonly Func<IValue, MyMainClass> _factory;

    public IValue Value { get; set; }

    public AnotherClass(Func<IValue, MyMainClass> factory, IValue value)
    {
        this._factory = factory;
        this.Value = value;
    }
    
    public void Worker()
    {
        var mainClass = this._factory(Value);
    }
}

You might ask how you should know what the signature of the Func is. In general that's one of those nasty ones. The Autofac solution is Delegate Factories (https://autofac.readthedocs.io/en/latest/advanced/delegate-factories.html) but these are not implemented that well in my opinion. You can always build strongly typed factories, but ultimately it comes back to someone somewhere knowing the signature of your parameter. The only real solution to getting these right and keeping them right is testing.

satnhak
  • 9,407
  • 5
  • 63
  • 81
0

Use the Method Injection method to connect to MyMainClass. Define a middle class that can access the main class with one method.

You will find useful and complete explanations in this source : dependency-injection

public abstract class MyAbstractClass
{
    protected IValue Value { get; set; }

    public MyAbstractClass (IValue value) 
    {
        this.Value = value;
    }

    public abstract void Configuration();

    public void Confirmation()
    {
        // Do something
    }
}

public class MyMainClass : MyAbstractClass
{
    public MyMainClass (IValue value) : base (value)
    {
    }

    public override void Configuration()
    {
        // Configure
    }
}

public class DataAccessMyMainClass
{
    public static MyAbstractClass GetMyMainClass(IValue value) 
    {
        return new MyMainClass(value);
    }
}


public class AnotherClass()
{
    public IValue Value { get; set; }
    MyAbstractClass _myMainClass;
    
    public AnotherClass(IValue value)
    {
        _myMainClass = DataAccessMyMainClass.GetMyMainClass(value);
        this.Value = value;
    }
}
Meysam Asadi
  • 6,438
  • 3
  • 7
  • 17