Example of dependency injection with base class only

Can DI be done without any third party tools? I read about how people do it with an abstract class and interface before they discover some DI framework. How is ID done in this most basic form?

0


a source to share


5 answers


Just pass the dependencies to the constructor of the class when you create it. No DI framework is needed when the project is small (below a couple of thousand lines of code) - you can write a factory and link all dependencies manually.



+4


a source


In this guide .

Basically what you do is that you DependingClass

only let know about Interface

and then implement that interface with IndependentClass

. With constructor overloads, you allow, for example, unit testing of frames to be dispatched to a mock object.
Some code might make it easier to understand what I am getting:

public interface IAnInterface
{
    void MethodOne();
    void MethodTwo();
}

public class IndependentClass : IAnInterface
{
     // Implements all members of IAnInterface
}

public class DependentClass
{
    private IAnInterface _dependency;

    public DependentClass() : this(new IndependentClass()) { }

    public DependentClass(IAnInterface dependency)
    {
        this._dependency = dependency;
    }
}

      



Now, as you can see, we have provided a default class type that will be generated if no argument is provided to the constructor. But we also allowed the injection of another class that implements the same interface, or a mock object of the same.

EDIT: As pointed out in the comment, it is probably better in a larger application to have a factory that instantiates DependingClass

and removes the default constructor. This way you only need to change in one place if you decide to change the implementation.

+2


a source


Of course, this is possible without third-party tools. Simple example:

interface ILogger
{
    void Log(string text);
}

class SomeClass
{
    private ILogger _logger;
    public SomeClass(ILogger logger)
    {
        _logger = logger;
    }

    public void DoSomeWork()
    {
        Log("Starting");
        // do work

        Log("Done");
    }

    private void Log(string text)
    {
        if (_logger != null)
        {
            _logger.Log(text);
        }
    }
}

      

SomeClass

takes ILogger

as input in the constructor. He uses it to record some result. Let's say we want it in the console:

class ConsoleLogger : ILogger
{
    public void Log(string text)
    {
        Console.WriteLine(text);
    }
}

      

In some code:

SomeClass instance = new SomeClass(new ConsoleLogger());
instance.DoSomeWork();

      

.., but instead we want the file to be written to the file:

class FileLogger : ILogger
{
    private string _fileName;
    public FileLogger(string fileName)
    {
        _fileName = fileName;
    }

    public void Log(string text)
    {
        File.AppendAllText(_fileName, text);
    }
}

      

So, instead, we insert the file logger:

SomeClass instance = new SomeClass(new FileLogger("path to file"));
instance.DoSomeWork();

      

SomeClass

happily not aware of the implementation ILogger

that is in use and just uses the one that was introduced. It's generally a good idea to create a factory creating instances of interface implementations instead of creating objects throughout your code to make it easier to change the implementation you're using.

+2


a source


You can create your components that interact with each other through interfaces and have your own hosting program that creates the components and links them together.

This will be your solution structure:

  • A collection of dlls that defines the contract between components (interfaces + data objects that are part of the interface method signatures).

  • One or more dll assemblies that define your components (that implement interfaces). Any communication between components is done through interfaces.

  • A compilation exe that starts the hosting process, creates the components and bundles them by setting some properties. Whenever you need to replace one component, you only need to change that project.

You can create unit tests for any of your components mocking the components that are used by the component under test.

Also you can get a fantastic read on property bindings from the app.confing file in your hosting project.

0


a source


There are three ways to do this ...

  • Pass a reference to the dependent instance (which is an instance of the class that implements the interface, of course) in the constructor.

    public class MyClass
    {
        private readonly ISpillDAL iSpDal;
        public ISpillDAL SpillDal { get { return iSpDal; } }
        public SpillLogic() : this(null) { }
        public SpillLogic(ISpillDAL splDAL)
        {
           iSpDal = splDAL ?? new SpillDAL();  // this allows a default 
        }
    }
    
          

  • Create a new object and then pass the reference to the dependent object using the property setter

    public class MyClass 
    { 
       private readonly ISpillDAL iSpDal; 
       public ISpillDAL SpillDal    
       { 
          set { iSpDal = value; } 
          get { return iSpDal; } 
       }
       public SpillLogic() { }        
    }
    
          

  • Use a function inside an object that takes a reference and assigns it to the provbate internal variable you created for this

    public class MyClass 
    { 
       private readonly ISpillDAL iSpDal; 
       public ISpillDAL SpillDal    
       { 
          set { iSpDal = value; } 
          get { return iSpDal; } 
       }
       public SpillLogic() { }    
       public void InjectSpillDAL(  ISpillDAL splDAL )
       {  iSpDal = splDAL; } 
    }
    
          

0


a source







All Articles