0

My Web API solution has 3 projects: controller layer, business layer, data access layer. Unity is installed in the controller layer project for implementing DI. Each class in business and data layer has an interface associated with it. Now how do i access a function in B business layer from A business layer, while complying with DI standards? Unity is not installed in business layer project. Currently what I am doing is:

public class BBusiness
{
    IBDataAccess bDataAccess;
    IADataAccess aDataAccess;

    public BBusiness(IBDataAccess bDataAccessParam, IADataAccess 
    aDataAccessParam)
    {
        this.bDataAccess=bDataAccessParam;
        this.aDataAccess=aDataAccessParam;
    }
    public function()
    {
        ABusiness obj=new ABusiness(this.aDataAccess);
        obj.functionInABusiness();
    }
}
user5663970
  • 89
  • 1
  • 11
  • Have a look at this answer https://stackoverflow.com/questions/40401900/bootstrapping-unity-composition-root-location/40403875#40403875 – Marcus Höglund Jan 17 '18 at 06:49

3 Answers3

0

From what I know (I´m quite new to DI) you should not create an object ABusiness within BBusiness.

What you should do is something like

public function()
{
    aDataAccess.functionInClassThatImplementsInterfaceIADataAccess();
}

Your solution means, that BBusiness is still dependend on ABusiness, which you want to avoid by using DI.

  • Could you please elaborate? I don't understand what you meant by aDataAccess.functionInClassThatImplementsInterfaceIADataAccess(); – user5663970 Jan 17 '18 at 06:49
  • You have your interface IADataAccess, and somewhere in your project you have a class that implements that interface, I assume. So, what you do using DI: First inject the interface through the constructor to class BBusiness. Then you can call methods of that interface: aDataAccess.functionOfTheInterface(); for example. This function must be implemented in some class, and what happens is, that that code gets executed without class BBusiness being dependend on ABusiness. Dependency Injection means, that a class does not create objects whose methods and functions it needs. – WhoMightThisOneBe Jan 17 '18 at 06:53
  • Another answer to what DI is, please see https://stackoverflow.com/questions/130794/what-is-dependency-injection?rq=1 – WhoMightThisOneBe Jan 17 '18 at 06:58
  • But i want to access the function which is inside ABusiness layer, not ADataAccess layer. So can i inject the interface for ABusiness (IABusiness) into the contructor here? Like.. public BBusiness(IBDataAccess bDataAccessParam, IABusiness aBusinessParam) – user5663970 Jan 17 '18 at 07:00
  • If the interface IABusiness is being implemented by ABusiness class, then that should work and you call the functions of ABusiness by doing something like aBusinessParam.FunctionOfABusiness(); – WhoMightThisOneBe Jan 17 '18 at 09:07
0

This is the whole idea of layers: you don't access functions in B from A. A is busy with its own business and don't even know of the very existence of B. B, however, is aware of A, aware of A's events (whatever kind of events A is providing) and reacts to them.

rs232
  • 1,172
  • 6
  • 15
0

Since ABusiness is a service that does something it would normally be setup like:

public interface IABusiness
{
    void functionInABusiness();
}

public class ABusiness : IABusiness
{
    // making the variable private readonly ensures that nothing
    // can set it after the constructor does (thus it can never be null)
    private readonly IADataAccess aDataAccess;

    public ABusiness(IADataAccess aDataAccessParam)
    {
        // Guard clause ensures you cannot set this.aDataAccess to null
        if (aDataAccessParam == null)
            throw new ArgumentNullException(nameof(aDataAccessParam));
        this.aDataAccess=aDataAccessParam;
    }

    public void functionInABusiness()
    {
        // Do something with aDataAccess
    }
}

Then you would add IABusiness as a dependency of BBusiness.

public interface IBBusiness
{
    void function();
}

public class BBusiness : IBBusiness
{
    private readonly IBDataAccess bDataAccess;
    private readonly IABusiness aBusiness;

    public BBusiness(IBDataAccess bDataAccessParam, IABusiness aBusinessParam)
    {
        if (bDataAccessParam == null)
            throw new ArgumentNullException(nameof(bDataAccessParam));
        if (aBusinessParam == null)
            throw new ArgumentNullException(nameof(aBusinessParam));
        this.bDataAccess=bDataAccessParam;
        this.aBusiness=aBusinessParam;
    }
    public function()
    {
        this.aBusiness.functionInABusiness();
        // Do something else...
    }
}

In your composition root, you would then setup Unity to associate IABusiness with ABusiness and IBBusiness with BBusiness. Do note that some projects use conventions that do this step automatically if the classes and interfaces are named a certain way or put in a certain place, etc.

container.RegisterType<IABusiness, ABusiness>();
container.RegisterType<IBBusiness, BBusiness>();
container.RegisterType<IADataAccess, ADataAccess>();
container.RegisterType<IBDataAccess, BDataAccess>();

The whole idea is that you do not reference the ABusiness class directly from the BBusiness class, so you can inject a different instance of IABusiness into BBusiness (for testing, or to create a decorator class around IABusiness that adds additional responsibility to it, etc.)

Also, the IABusiness interface might be in a different assembly than ABusiness (for example), so the BBusiness assembly doesn't need to reference the ABusiness assembly.

Do note you are not following Microsoft's capitalization conventions, which may make this code difficult to maintain for those following you. Method names should be Pascal case in .NET, like FunctionInABusiness().

NightOwl888
  • 51,095
  • 20
  • 122
  • 194