I've followed the msdn document on the onion architecture in .net core here, but it seems you can't really have the UI only know about the service layer, without duplicating code. On the last part of the article (The UI), the startup file is accessing the repo. Is this logical? If so why?
On the last part of the article (The UI), the startup file is
accessing the repo. Is this logical? If so why?
I believe you are referring the following code -
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserProfileService, UserProfileService>();
It is normal for UI Project to reference other projects, and register dependencies in IoC container, because Composition Root should be placed as close to the application's entry point as possible.
var userService = new UserService();
If you instantiate UserService using new keyword in UI, they become tightly coupled - a change in one class forces a change in another.
IoC container solves the dependencies issue by resolving dependencies at runtime and pass them as needed.
If you want to know more about DI, you might want to read Dependency Injection in .NET by Mark Seemann and Adaptive Code via C# by Gary McLean Hall
Related
I am relatively new to the concept dependency injection, so I am unsure about how it prevents cyclic dependencies. Let's say I have followed projects (the sample project structure might not be good but please bear with me)
Project A:
Domain Layer
IRepository
Project B:
RepositoryImpl --> implement IRepository interface
In this case Project B will need to reference Project A. But to set up Project A, let's say Unity Container, Project A will need to reference Project B in order to have something like this in the Unity Config.
container.RegisterType<IRepository, Repository>();
But doesn't this introduce cyclic dependency? Or is it I'm having wrong understanding in either Dependency Injection or cyclic Dependency? or even both?
You are missing an important concept here, which is the concept of the Composition Root. The best and most elaborate description of what a Composition Root is, can be found here. To summarize:
A Composition Root is a (preferably) unique location in an application where modules are composed together.
As the article explains:
Most classes use Constructor Injection. By doing this they push the responsibility of the creation of their dependencies up to their consumer. That consumer -again- push the responsibility of the creation of its dependencies up as well.
We can’t delay the creation of our classes indefinitely. There must be a location where we create our object graphs. You should concentrate this creation into a single area of your application. This place is called the Composition Root.
Only the application's entry point contains a Composition Root, any other libraries in application do not.
This means that the Domain Layer itself does not register its types into the DI Container—only the startup project does this. When you do this, the Domain Layer will therefore not have to depend the Data Access Library (your Project B).
Both the first edition (chapter 2) and second edition (chapter 3) of the book Dependency Injection in .NET contain a elaborate discussion of an example that is very close to the application structure given in your question. The previously referenced Composition Root article is an excerpt from the second edition. The first chapter can be read for free online.
So, this is the first time I'm dealing with DI, please correct me if I misunderstood the whole DI thingy.
These are few of my projects:
Web Application/ Web API Project - Depends on Service Class + inject Automapper (Configuration only applicable for current project)
Service (Class Library) - Depends on Data Class + inject Automapper (Configuration only applicable for current project)
Data (Class Library)
My intention was to have each project having its own DI container (says Unity DI). I'm not sure that each project can have its own DI container.
I have read some of the article, showing that it cannot be done (not sure if i interpret them correctly) but I'm not sure why?
If it cannot be done, can anyone explain it and how can I achieve this and I doesn't want to register the classes in Data Layer in the Application Layer DI.
If each project can have its own DI, when registering the IMapper as instance will it override IMapper of other layers?
My intention was to have each project having its own DI container (says Unity DI). I'm not sure that each project can have its own DI container.
As explained here, you should compose all object graphs:
As close as possible to the application's entry point.
This place is called the Composition Root:
A Composition Root is a (preferably) unique location in an application where modules are composed together.
In other words, the only place that you should use your DI container and configure your application's dependencies is in the start-up project. All other projects should be oblivious to the container and should purely apply Constructor Injection.
I have read some of the article, showing that it cannot be done
It can be done, but you shouldn't.
If each project can have its own DI, when registering the IMapper as instance will it override IMapper of other layers?
This problem goes away if you apply the Composition Root pattern. In the Composition Root you have full control over which component gets which dependency.
PRO TIP: Read this book.
I have a solution with multiple projects - similar to below:
WebAPI
ICustomerService.cs
Business Logic
CustomerService.cs
IDatabaseService.cs
Database Access
DatabaseService.cs
Previously the WebAPI project had a reference to the business logic, then that had a reference to database access. I am trying to invert this logic.
Currently, I am using Unity in my WebAPI project to resolve the interfaces with implementations from the business logic layer, however once I have inverted my logic so that the business logic layer has a reference to the WebAPI layer the Unity registration doesn't work without a circular reference:
var container = new UnityContainer();
container.RegisterType<ICustomerService, CustomerService>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
When I am trying to register my types, the ICustomerService lives in the top project, CustomerService is invisible to it.
I have read about having a separate project to house the unity configuration but that would create a circular reference also. How can I make this work?
Why do you wanna invert that? Seems to me like the only way of doing it. The WebAPI project is the main entrance (if it was self-hosted, it would contain a programs.cs). This project would also contain your composition root for setting up dependency injection and resolving types (this is handled by the WebAPI). See also Composition Root. Could you explain to me the benefit of doing this?
Also be aware that it is bad practice to spread out the IoC container cross projects. Only the composition root (main) should know about the fact that Unity is being used. Also avoid using the ServiceLocator pattern.
The objects in the different projects should just have a reference/dependency through for example the constructor.
If you think about it like that the Controller is dependent on ICustomService, CustomerService is dependent on IDatabaseService.
Also a note: I would put the implementation and interface in the same projects.
WebAPI
Controller
Business Logic
ICustomerService.cs
CustomerService.cs
Database Access
IDatabaseService.cs
DatabaseService.cs
You are on the right path. Your controller should inject the icustomerservice implementation in the constructor and the service should inject the idatabaseservice in its constructor.
public FooController(ICustomerService svc)
...
public CustomerService(IDatabaseService db)
...
And add the database DI config
container.RegisterType<IDatabaseService, DatabaseService>();
container.RegisterType<ICustomerService, CustomerService>();
When you are ready to use the new implementation, just change the reference in the config to instantiate the new implementation.
The interfaces should be in a project together and the implementation should be in a project together. The new and old implementation should share a common interface.
I have three layers in my solution, Presentation (winforms project), Domain (class lib) and Persistence (class lib).
I am trying to implement dependency injection to decouple them.
My application root is in my presentation layer.
I understand the only time the DI container (unity in this case) should be referenced is in my application root, otherwise I would be simply replacing class dependencies all over the place with a dependency on my DI container (which I suppose is still slightly better).
So with these foundation concepts in mind, I am really struggling with the specific implementation. Perhaps my application root should be in its own seperate project - perhaps a console application. I can then resolve the first 'overallApplication' class, listing IPresentation, IDomain and IPersistence in its constructors. I understand (assuming actual implementations have been registered) the unity framework would then recursively solve all respective sub-dependencies.
In your experience - would you be able to advise if this was a sound approach. I really understand the concept and importance of decoupling, and how this is solved by DI conceptually at a high level, but I am struggling to tie it all together in a real application solution with multiple layers (organised in VS as seperate projects).
Any help or pointers towards examples of proper implementations would be greatly appreciated.
Some thoughts for you in hope that they help.
Throughout your question you make statements such as:
"I really understand the concept and importance of decoupling, and how this is solved by DI..."
The first thing I would evaluate is the understanding that DI != IoC Container (e.g. Unity).
An IoC container is used to remove boilerplate code that results from an existing DI structure. As such I would suggest you refactor without Unity /first/. Then go back and add Unity to reduce your code.
So that:
-1. Make application Di via manual Ctor, Property, Method, Service Locator injection methods.
-2. After this is setup you should see things like:
public View() {
var controller = new Controller(new IView(), new model(), new IService(new Dal(ISession(connectionString))), new , new ILogger(), etc.){}
}
-3. Then once you have something like this in your code you can then use Unity to inject all that fun:
public View() {}
Controller Controller {get;set;} //<- Unity auto builds & populates this for you with all the "new" items normally found in your constructor (or wherever).
While not a production example, it should give an idea of some steps to refactor. Going straight to Unity will put the cart before the horse, so to speak.
Say I have the following 4 .net assemblies:
Winforms UI
Business Logic
SQL Server Data Access (implementing an IRepository)
Common Interfaces (definition of IRepository etc.)
My business logic (2) makes calls to the data access layer (3) through IRepository (defined in 4) using constructor dependency injection. However when I ceate a business object I need to pass in an actual repository. I do this by having a singleton class in my business logic layer return the currently in use concrete object implementing IRepository. I am coming to the conclusion that this is a bad thing, as my business logic layer now has to reference 3 as well as 4.
I think I need a IoC Container but the question is where I create/put it as it seems that wherever I create this (1 - UI)? will also need to hold a reference to 3 (SQL Server Data Access). Am I not just moving the problem rather than achieving actual decoupling?
Do I create the IoC Container in the UI. Or expose it through another new assembly.
(I'm using C#, .net 3.5 and AutoFac)
Thanks.
IoC container generally should be created in the host project (application entry point). For the Windows.Forms application that's the exe project.
Generally in simple solutions (under 10 projects), only a host project should have a reference to IoC library.
PS: Structuring .NET Applications with Autofac IoC
When registering components there are several possibilities:
Registration in code:
directly
Problem: you have to reference everything ( you are here)
indirectly
Problem : to find out what has to be registered
Solution:
use attributes
use marker interface as IService
use conventions (see StructureMap)
Registration with configuration file:
let the container do everything
read the file yourself
Top level is a way to go (UI, as Rinat said).
Now as for references, simplest way is just to go over all assemblies in the current folder and use some convention to get the services out. Attributes work fine, putting registrar classes in each assembly works fine, whatever suits you. The code for extracting everything should probably be in a separate assembly, unless your IoC framework already does that.
The module distinction and the "scopes" defined by the modules exist mostly at compile-time. In the run-time it's all one big mess ;) This is used by most IOC containers and they don't really care about where they are located. The IoC container for a web-app will typically be created at the outermost level (very close to the web-container itself).
It's true that you could create it anywhere, but I'd introduce an extra layer, let's call it 3.5.
Your current 3 would be where your IoC resides for Data Access - this would become a wrapper for your actual DAL. Based on your config, 3 would create either a mock repository or a concrete one.
So 2 still references 3, but it's just an interface to the actual DAL which is configured through your IoC framework.
Alternatively, you could roll your own 'el-cheapo' IoC - change your Big Ugly Singleton to a Static Gateway - Abstracting IoC Container Behind a Singleton - Doing it wrong?