My group of projects is as follows:
1) Shared Class Library
Models
Entity Framework Classes (DB Contexts etc)
2) Web API
Uses the models and entity framework classes in (1) to communicate with the database.
3) Console Application
Creates instances of Models in (1) and saves them to the database using the entity framework classes there.
My question is:
Should I be creating a single DI Container class that has a ConfigureServices method that is shared between both the Console Application and the Web API?
Or does it make more sense for each of these applications to be responsible for binding their own dependencies?
Thanks in advance!
Ioc registrations
It depends on the nature of applications but in general i would say you want to split it up and have it in either application. Things that are the same in both application don't need abstraction and ioc registration (don't make things abstract that are not needed to be abstract).
That said, you see microsft uses the extension method pattern to add multiple demendencies at once like: services.AddMvc() is an extentension method to add 20 or so ioc registrations. You could do the same in your shared library. and simply add services.AddSharedLibrary() in your startup classes:
public static class MyServiceExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCOllection services)
{
services.Add<Interface1,Implemenetation1>();
services.Add<Interface2,Implemenetation2>();
return services;
}
}
Startup base class
You can also make an (abstract) base class for the Startup Class. But this would mean that your Shared library now needs dependencies on the HttpBuilder/Kestrel nuget package. which would be weird if you where making a Servicebus queue listener for example.
A good reason to make a base class for Startup is: if you want all your startup projects to have the same way and order to build up the Appsettings and/or you want them to use the same Appsettings as configuration for IOptions. But in this case i would recommend making a separate shared library for this that is specifically aimed to provide the same StartupBase and configuration.
Related
Have a project structure where I have a couple of layers
Api
Bll
Dal
Utility
When say a order request is received by the Api there is a couple of steps that we need to take.
Like:
Validate the input
Save the customer
Save the order
Validate payment
Save final order status
All of these require different classes from the Bll
And the classes inside the Bll requires classes from Dal and maybe other Bll or from Utility.
So now inside the Api I need to register the whole chain of what might be needed like
Register<IValidateService,ValidateService>()
Register<ICustomerService,CustomerService>()
Register<ICustomerDatabaseService,CustomerDatabaseService>()
Register<IUtilityService,UtilityService>();
Maybe all of the above just to get the CustomerService working, and then we need to do this for a lot more services and I will have to reference the Dal layer inside the Api layer.
And in the long run I feel that everything will become really bloated.
Would be good if I could just Register the CustomerService and then that will register it's dependencies by itself or something.
Maybe it is fine to have the entry level to be aware of everything?
Any ideas on how to solve this or am I overthinking things?
Thank you
My suggested solution for auto-registration is the following:
Use Autofac.
Create a public DependencyModule class derived from Autofac.Module in your Api, Bll, Dal and Utility projects.
Override the Load method and register only types that are in that project.
In your startup project (Api) use my nuget package to automatically discover and register all your DependencyModule classes into the DI container.
At the end you will have something like this:
Utility
DependencyModule.cs - registers all the utility types that need to be injected.
Dal
DependencyModule.cs - registers all the DAL types (e.g. DbContext) that need to be injected.
Bll
DependencyModule.cs - registers all the BLL types that need to be injected.
Api
DependencyModule.cs - registers all the API types (if any) that need to be injected. E.g. filters, etc.
In Program.cs or Startup.cs you register only my Autofac module that will discover and register all your modules above.
See my example solution's description and implementation.
This way each injectable type registration is done in its own assembly and dependent services do not need to worry about it.
Alternative solution - uses Microsoft DI
Instead of Autofac modules you can create extensions methods for IServiceCollection type in each of your project and register the types that are in that project.
Then in your Program.cs or Startup.cs just call each extensions method.
At the end you will have something like this:
Utility
IServiceCollectionExtensions.cs - registers all the utility types that need to be injected.
Dal
IServiceCollectionExtensions.cs - registers all the DAL types (e.g. DbContext) that need to be injected.
Bll
IServiceCollectionExtensions.cs - registers all the BLL types that need to be injected.
Api
IServiceCollectionExtensions.cs - registers all the API types (if any) that need to be injected. E.g. filters, etc.
In Program.cs or Startup.cs call each of the extensions methods.
Note
Actually you can combine MS DI with Autofac so that you can enjoy the advanced features of Autofac and use specific extension methods for IServiceCollection at the same time.
In that case you should know that the order of registrations is this:
MS DI registrations: ConfigureServices() method
Autofac registrations: ConfigureContainer<T>() method
All the MS DI registrations will be populated into the Autofac container.
Dependency injection should be done at the application layer, which means the application must specify (effectively, choose) all of the dependencies in order for it to work correctly. This does mean it will be "bloated" in the wiring/startup phase, and does mean the app layer will have to deal with dependencies it might not normally care about.
That said, there's nothing wrong with your library code providing sane base implementations and wiring of these to alleviate the app layer's burden of figuring out what to wire up.
That means you can do one of
add the statements for registration manually and explicitly in your startup (total control, and extremely obvious how things are setup)
create a convenience method that contains common wiring in your library (less control, but less code to deal with when wiring). This is common in ASP.NET (see the AddXxx() and UseXxx() patterns).
discover dependencies. This uses reflection (usually) to find the implementations of all the dependent interfaces, and auto-register them). This is usually from a third-party like AutoFac. It's not built in to .NET.
Trying to implement clean architecture in a new project, but with some restrictions: I want to loose dependencies as much as possible.
Basic:
Solution has several projects:
WebApi
UseCases (referenced by WebApi, implements business logic)
Gateway (referenced by UseCases, provides repository interfaces to UseCases)
DataAccess.EfCore (referenced by Gateway, implements access to MSSQL)
Domain.Core (Domain model is here)
What is desired and what problems are solved and still here:
- All projects has IHostingStartup implementations where they are configure themselves: UseCases registering some behaviours, Gateway - it's interfaces, EfCore - configuring DbContext and registering it.
Looks fine. Almost. There two architectural problems for now:
Configuring ASP.NET Core Identity. Usually it is done in the WebApi project, but in this case I have to reference EfCore project to be able to write this:
services.AddIdentity<User, Role>().AddEntityFrameworkStores<MyDbContext>();
class "MyDbContext" is declared in EfCore project, so this one line has settings from two worlds:
AddIdentity() : WebApi world
AddEntityFrameworkStores() : DataAccess world (because "MyDbContext" class is belong to it)
If I put Identity configuration into the DataAccess - then I have to configure such things as Identity lockout settings and Login/AccessDenied pages in the DataAccess what is also wrong and what should not be done there.
Is it possible to split the configuration, so DataAccess.EfCore will just register DbContext store for identity and WebApi is configuring lockouts and other stuff?
I'm using user secrets to store connection strings. How to pass it to the IHostingStartup implementation to configure DbContext? Method signature is allowing to work with IWebHostBuilder builder only, so I'm stuck here also.
Any ideas, help, experience?
UPD:
Or, almost forgot about 3rd problem:
When I'm running the app at first time - I want to seed some data into the DB. And the problem here is to seed the IdentityUser entities as they should be added through UserService (password hashing etc), but at the same time I want to do it in the DataAccess.EfCore project: I'm using FluentAPI to configure the models and seeding the data with "HasData" method. So any idea here would also be appreciated!
if you refer with "Clean Architecture" to Uncle Bobs article and book (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) then your project setup needs a little cleanup.
In Clean Architecture Gateways depend on use cases, not the other way round. One key principle in this architecture is "inversion of control": you define interfaces in the inner circles and keep the implementations details (like EF, DbContext and other frameworks) in the outer circles.
The wiring of the interfaces and implementations happens in the "main component" - which in asp.net core would be the startup class.
More details on implementing Clean Architecture (e.g. in Asp.Net) you can find in my blog series: http://www.plainionist.net/Implementing-Clean-Architecture/
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'm trying to design WebApi application with using IoC like Ninject. I have the following layers(3 projects):
Domain(Repository) layer
Service
Web API application core
The Repository layer has interface IRepository<T> and a few implementations of it. And in the Service also exists interface IService<T> with a two different implementations.
Could you please advise me should I use DI container (Ninject) in WebApi project to bind IService<T> and ServiceConcrete<T> and DI container in the Service project to bind IRepository<T> and RepositoryConcrete<T>?
Or maybe should I use only one DI in WebAppi project?
A practical way I have found to set up Ninject modules can be found below.
Overview
Create an assembly called DependencyResolution
Create the Ninject modules (that you will utilize in your WebAPI project)
Have only this DependencyResolution and your Domain projects referenced in your WebAPI project
Initalize/register your modules in NinjectWebCommon.cs
Details
Should be easy as create a project, add Ninject as reference from NuGet for instance.
Add new class file(s) to this project named after the modules you want to create like: ServiceModule.cs, RepositoryModule.cs, etc.
Create your Ninject module(s). For detailed instructions on this you can refer my answer on this.
In your WebAPI project, you add reference to this just created DependencyResolution project and your Domain project.
Initializing/registering your just created module(s) in the WebAPI project's NinjectWebCommon.cs as:
private static void RegisterServices(IKernel kernel)
{
var modules = new List<INinjectModule>
{
new ServiceModule(),
new RepositoryModule()
};
kernel.Load(modules);
}
I will also try to address another concern that is loosely related to your question. I think your current layering setup would need a bit to be changed.
The basic and probably my biggest problem with your layers are that you mix up and therefore tightly couple the Domain and Repository which is clearly an infrastructural concern.
I would suggest to re-architect your layers as:
Domain
Services
Infrastructure (Repository implementations could go here for instance)
Dependency Resolution
WebAPI
Do not forget that your Domain layer should not have any idea about infrastructural details like Repository, else you are going to tightly couple your domain with unneeded implementation details.
EDIT: From the comments I see that you have some concerns about where to place and how to name things which is obviously one of the hardest things in programming.
So my thoughts on clearing this confusion up are:
Layer: is a logical separation or collection point of classes, methods, etc. that those belong together.
Each layer can consists of multiple projects or assemblies. So if you want to categorize your projects into layers, you could create directories in your solution named about your layers and place the individual projects inside these directories. It's really just a matter of taste in the mouth, take it just as a tip.
Example structure
Solution root
Core directory
Domain assembly: the root of you domain where you have your business or domain entities AND the all the interfaces that your domain is using.
Domain services assembly (just could be in Domain assembly as well)
Services directory
Application services assembly: for example an example this assembly houses services or facades that spans operations accross multiple domain entities or aggregates, etc.)
Infrastructure directory
Repository assembly: this is where you have the implementations of your EF repositories
Custom logging/email/whatever else assemblies or implementations that doesn't belong to the domain.
DependencyResolution assembly: this is the place of your NInject modules and all IOC container related wirings.
UI directory
WebAPI assembly
Asp.Net MVC assembly
Summary
The Dependency Resolution project has references to any needed assemblies (Domain for interfaces, Services/Infrastructure for their implementations) and wire them altogether for later use.
The WebAPI project would only need to have reference added Domain and Dependency Resolution so then you could just ask for your interfaces in your WebAPI methods/functions public constructor and Ninject will do the dirty job for you behind the scenes.
Please don't forget that this is just an easy quick 'n dirty architecture suggestion of mine, without knowing your exact requirements and use cases.
If I understand your question, you're having troubles configuring your Repository layer because your config code is in your application layer, which probably only references your service layer (which in turn references your repository layer). What I've done in order to get around this is first create your configurations in modules (these can live on any layer, but you must reference Ninject)
For your repo layer:
public class RepoNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMyRepo>().To<MyRepo>();
}
}
create a similar Module in your service layer:
public class ServiceNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMyService>().To<MyServce>();
}
}
Then, in your application layer, you can load the modules dynamically (this is what NinjectWebCommon.cs looks like):
private static void RegisterServices(IKernel kernel)
{
kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
}
More info on modules: https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel
We use ninject as our DI solution. How do I create a self sustaining class library dll with its own internal IOC. Basically I have created a service that does something and I want to register the bindings in the dll and just hand it to other people. I don't want them to care about any binding in my dll.
In the dll:
public class FirstService : IFirstService
{
public FirstService(ISecondService secondService, IThirdService thirdService)
{
//Saves locally
}
//Does stuff with second and third services
}
What the end user does:
public class ThirdService : IThirdService
{
//Create the actual implementation of this
}
What I want inside the dll:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFirstService>.To<FirstService>();
kernel.Bind<ISecondService>.To<SecondService>();
}
I don't think I want to use IKernel here though, due to possible memory leakage.
There are 4 basic design approaches to DLLs that are commonly in use:
An application layer.
A plug-in.
A library.
A framework.
It sounds like you have one of the last 2, but it is not possible to tell based on your question which prototype you are referring to.
For an application layer, you would typically compose the components inside of the application, in the composition root, as close to the point of entry of the main executable application as possible.
For a plugin, it would typically have its own internal composition root that is fired by some method or event of the application it is plugging into (based on that application's composition root). This is sometimes facilitated by modules in DI containers.
A library would typically not have any internal composition, but would provide an API (sometimes implemented as a fluent builder) that makes it easy for the client application to compose the pieces together. See this post for a couple of ideas about how to do that.
A framework would need to have 1 or more explicit extension points for the application to integrate into. Think of how MVC controllers work. There is an internal scanning implementation that by default can instantiate any object that implements a certain interface. There is also an abstract factory that can be used to inject dependencies if the default constructor is not available (in MVC, that is IControllerFactory). See this post for more information about how to make a DI friendly framework.