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.
Related
I have WebAPI (.NET 5) project that hosts services to be called from other (web) applications.
And, I would like to use Dependency Injection to get some service classes inside of my business objects.
Naturally, all calls to my project are going through Controllers that can receive IServiceProvider which will allow me to GetRequiredService().
All is good inside of the controller instance. But some/many of my business methods are not created by the Dependency Injection engine and as a result, I don't have access to the service provider and the only way to get data from the DI is to pass the instance of IServiceProvider manually to required business objects. Obviously, that will add up excessive code which will reduce readability.
What can I do to avoid passing the instance of IServiceProvider to my business objects and still be able to access it?
One solution I see is to create a static global object (_globalServiceProvider), but I'm afraid this will ruin the whole idea.
Anyone can recommend a better solution?
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.
The short question is:
Given a library warrants using a particular IOC container for its internals, when an application consumes that library, given the app warrants using an IOC container for wiring its dependencies, given if the the two containers are different, how can they play well together?
The scenario is, the application has classes defined that depend on types from the library. So when the application container attempts to build such a class, it needs to know how to resolve the type that lives in the library.
Here's the long winded question:
This question does seem to have been asked in different shapes and form before on SO, but I can't seem to find the answer I need so I am going to have a go at it with a hypothetical _over_simplified_ concrete example.
We want to write a library for logging that users can include as a package in their solution to get logging functionality out of the box.
The public interfaces the library exposes are..
public interface ILogger {}
public interface ITarget {}
Concrete implementations are
internal class Logger: ILogger { public Logger(ITarget target) {}}
internal class FileTarget : ITarget {}
Requirements are if the user includes our package and defines a class with a property of type ILogger or has a ctor argument of type ILogger then our library is responsible for injecting a concrete implementation for that interface into the user defined class. By default that injected logger will go to the file system for logging because the default implementation of an ITarget injected into the ILogger implementation is a FileTarget by our library.
If the user decides to write a class implementing the ITarget interface then our library will use that to inject into the Logger class and not use its default FileTarget implementation.
SO what I wish to demonstrate, is their is a bi-directional dependency here.
Our library depends on the user's assemblies, since it needs to scan the user's assemblies to load any extension points (i.e. an ITarget implementation) and inject those into its own objects ahead of any default implementations.
The user's assemblies depends on the library, since if the user chooses to define a class with an ILogger interface as a dependency, then that user object should get a concrete reference to that interface provided at runtime by our library.
The easy solution is if the user and our library are both using the same IOC container, then problem is solved. But this is a strong assumption. What I wish to do is
Use an IOC container with the library that caters best to the library's requirement, in my case its Ninject.
At run time somehow provide a mechanism for the user to call via some API into my library that will ensure Ninject is fired up and it scans the user's assemblies, and wires everything taking into account all extension points.
So far so good, its perfectly achievable, but here comes the tricky part.
if the user is also using Ninject, then problem automatically solved, since Ninject already knows how to resolve Interfaces living in our library. But what if the user decides to use his/her choice of IOC container?
I almost want to define some sort of child container functionality in the library with an interface like such
public interface IDependencyResolvingModule { T Get<T>(); []T GetAll<T>(); }
and provide an implementation that uses our library's choice of container (i.e. Ninect) to resolve the type requested in the two methods define above.
I want the user's IOC container to have some functionality where if it can't resolve a dependency (i.e. an ILogger), it should hook into the IDependencyResolvingModule implementation and ask for the dependency.
This way our library gets to use its choice of IOC Container, and the user's code has a way to resolve dependencies that its IOC container has no clue about. Wouldn't this solution work if IOC containers out there some how provided functionality to register singleton instances of any IDependencyResolverModules found in assemblies in the executing assembly's dir and when they can't resolve a type, ask any of the singleton modules?
But barring a solution that requires every other IOC container to accommodate, how else can this be solved? SO the problem in a few lines is, when a third party assembly chooses to use an IOC container for its internals, what is an easy solution such that this library can simply provide a mechanism for an IOC container sitting outside to hook into and resolve dependencies that live in the library.
I see few possible approaches here:
Write default registrator for all of the popular IoC containers. Each of them should be placed in the separate assembly. Then developer can choose the one he needs and configure his container with it.
Define your own factory abstraction and write default implementation that will return the default logger. Let developer to substitute implementation of that factory. For example, with adapter for his favorite container. This approach is most container-agnostic, because developer can just use the default factory implementation. But this way has nothing to do with auto-wiring.
The lazy variation of the first approach. Write small manual about configuring a container to work with default implementations. Then developer could configure the container himself.
Combine all previous solutions to satisfy every developer. :)
EDIT: added example of integration of two containers
var allPublicInterfacesFromLibrary = typeof(AnyLibraryType)
.Assembly.GetTypes()
.Where(t => t.IsInterface && t.IsPublic);
foreach (var libraryInterface in allPublicInterfacesFromLibrary)
{
var local = libraryInterface; //to prevent closure
applicationContainer.Register(
Component.For(libraryInterface)
//delegate resolving
.UsingFactoryMethod(k => libraryContainer.Resolve(local))
//delegate lifetime management
.LifestyleTransient()
);
}
I’m new to Dependency Injection and had a question/need guidance.
I had an application that used the repository pattern for data access. I used StructureMap to get the correct repository and all worked well.
I have since broken out my model (including the repository logic) into its own assembly and added a service layer. In the interest of DI the service layer class takes an IRepository in its constructor. This seems wrong to me as now all consumers of my model need to know about the repository (at least configure their DI to know which one to use). I feel like that is getting into the guts of the model.
What sounds wrong with this?
An application written to use dependency injection typically configures a single container instance where all the interface/implementation type mappings have been registered at an initialization stage of the application. This would include the registration of the repositories, services, and any consumers of the service within the application.
By resolving the consumers of the service through the container, consumers need only indicate their dependency upon the service, not any dependencies the service might need. Therefore, the consumers of the service will not be coupled to its dependencies (e.g. your repository). This is the benefit of doing dependency injection through a container as opposed to doing manual dependency injection.
If you are designing services to be consumed by other applications in the form of a reusable library then your options will vary depending on the level of flexibility you wish to offer.
If you presume all clients of your library will be using dependency injection, then you will need to provide an appropriate amount of documentation about what types need to be registered within their container.
If you presume all clients will be using a specific container (e.g. StructureMap), then you can ease the registration requirements by providing registries which encapsulate all the specific registration needs for the client.
If you wish to allow your library to be used by clients not using their own dependency injection container then you can provide a static factory which returns the service. Depending on the level of complexity, such a scenario may not require use of a container (for example, if your service is comprised by just a few objects in all). If your library is comprised of a substantial amount of components which need to be composed then you might have factories which resolve the services through their own shared internal infrastructure initialization needs.
I understand your dilemma there Dan, I too spent lots of time wrestling over that in my mind. I believe the way I decided to go forward with was one of best ways to encapsulate all of the concerns and still have easily maintainable loosely coupled objects.
I wrote this blog post specifically about NHiberante but if you look at the repository pattern in implement you can easily change the NH specific code to use your backingstore.
Creating a common generic and extensible NHiberate Repository
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?