I am very new to ASP.NET Core.
If I create 4 projects like this:
MyApplication
|-- MyApplication.DataAccess
|-- MyApplication.Provider
|-- MyApplication.Service
|-- MyApplication.ViewModel
DataAccess project is for getting data from the database, Provider for the queries, Service project for business logic, and lastly ViewModel for the data representation.
The dependency is like this:
MyApplication.DataAccess -> MyApplication.Provider -> MyApplication.Service
and also:
MyApplication.ViewModel -> MyApplication.Service
My target is to later create an application named MyApplication.Web.UI for the Razor pages.
I am very confused on how to create a dependency injection in the case of class library in C#. Is there any way for me to use DI Service or is it better to use using scope for my DBContext?
And lastly, is there a way where I can convert the DataAccess models into view models in the Service project without making the Service project depending on the DataAccess project?
I am very confused on how to create a dependency injection in the case of class library in C#. Is there any way for me to use DI Service or is it better to use using scope for my DBContext?
You don't want your db context to "bleed" outside of your Provider project (that's what your ViewModel project is for).
Use Microsoft.Extensions.DependencyInjection with an interface registration for each service in your Provider and Service projects. The usual pattern is for implementations of those interfaces to remain internal to the project and add a public extension method in the project which registers the service interface using the internal implementation such as this:
public interface IMyService { ... }
internal class MyServiceImplementation : IMyService { ... }
public static class Extensions
{
public static IServiceCollection WithMyService(this IServiceCollection services)
{
// method used here depends on the required DI scope for the service - be sure you understand transient vs scoped vs singleton
return services.AddTransient<IMyService, MyServiceImplementation>();
}
}
Then your web project (or other client) takes a reference to the project and configures its DI container using the extension method (setup is different for different clients [ASP.Net for example has a specific place where services are to be registered, you don't create the service collection or build the service provider], but the gist is this...)
IServiceCollection svcCollection = new ServiceCollection();
svcCollection.WithMyService();
var serviceProvider = svcCollection.BuildServiceProvider();
The result of all this is that you have service interfaces which can be easily unit tested (by replacing dependencies with a framework such as Moq) and your implementation remains suitably encapsulated. Changing to a different implementation for a service now just entails providing a suitably named alternative extension method which supplies a different implementation class to the DI container and the client systems are unaware of the change: a clean separate of concerns.
I think you could create a project for Composition Root (unique location in an application where modules are composed together.) that references all other projects.
you could also check similar cases like:case1,case2
Related
I'm trying to understand that in a multi layer project where we should register dependencies. I'm using ASP .NET Core to create a project which will have a Web application and 3 or more logical layers(class libraries) lets say Business Layer, Data Access Layer etc. Business Layer can have 1 or more classes and so the other layers.
My question is should I register all the dependency(of all the classes of the class libraries) in startup class(by extending IServiceCollection) of web application.
like:
namespace Architecture.Web.DependencyExtension
{
public static class BusinessLayerDependency
{
public static IServiceCollection RegisterDependency(this IServiceCollection service)
{
// register dependency for classes of business libraries here
service.AddTransient<IOrderBizObj, OrderBizObj>();
return service;
}
}
}
Or should I extend the IServiceCollection into class libraries and do the registration as answered in this question?
When I go through this article It is saying that all the dependency should be register at the composition root of the application. It also motioned that "The Composition Root can be spread out across multiple classes as long as they all reside in a single module".
Thanks in advance.
I've been trying to follow an asp.net mvc core tutorial online and I noticed that when using entity framework you can enable it in ConfigureServices in the application start up file like so:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyContext>(cfg => cfg.UseSqlServer());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
but what if I intend to use an n-tier architecture having different projects for the domain and data layers?
So I wouldn't have a reference to EntityFramework or the DBContext in my API layer as these would be separated by a domain layer?
The only solution that comes to mind is to add the Context to a "Common" project but that doesn't feel like the right thing to do?
How would you guys solve this?
This problem is negligible in terms of architecture, but if you are really concerned about separating the EF dependencies into a separate project then you can just separate the dependency injection layer alltogether into separate project and use reference only to that in multiple other projects.
EDIT:
I may not have been elaborate enough on this so here is an example of what I meant. I assume your Example.Domain has some repository which references the your EF YourDbContext
public class YourDomainRepository
{
private readonly YourDbContext _context;
public YourDomainRepository(YourDbContext context)
{
_context = context;
}
...Other repository methods
}
The issue you are describing is that it's not enough to just reference the Example.Domain in your Example.Api because in order for the DI to work you need to add it to the services and you need to add both YourDomainRepository and other services on which it depends (like YourDbContext) which in turns what requires you to reference EF libraries.
So the approach I tried to propose is either:
Option 1 - you create another project for common stuff like DI. That project would house a function like below:
public static class YourDomainDIExtensions
{
public static void AddDomainDataServices(this IServiceCollection services)
{
services.AddDbContext<YourDbContext>(...);
services.AddTransient<YourDomainRepository>();
}
}
Option 2 - you don't create a new project and just have the same extension class in your domain project.
Either way this abstracts the EF dependencies from your Example.API and in there you will just call:
services.AddDomainDataServices();
Which effectively is reusable across multiple projects.
What I am currently doing is creating an extension in my business logic project which has a reference to the data access project that encapsulates EF Core.
The structure is the following:
API (ASP.NET Core API - references Services)
Services (Business Logic - References DataAccess)
DataAccess (EF Core Here)
In my Services project I have an extension like this:
public static class AppExtensions
{
public static IServiceCollection SetUpAppDependencies(this IServiceCollection serviceCollection,
string connectionString)
{
serviceCollection.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
return serviceCollection;
}
}
Then in ConfigureServices I do this:
// connectionString should come from KeyVault or Configuration
services.SetUpAppDependencies(connectionString);
You only need entity framework in the project (i.e., tier) that actually touches the database. Other projects in the solution can add a reference to the project encapsulating entity framework. For example:
This is a simplistic example, but the Data project has references to EF. The UI project has references to the Data project. In larger projects, I might even have an API project in between the Data and UI tiers. In those cases, the UI project wouldn't reference either the Data or API projects, as it is entirely UI. That is, the UI project wouldn't have controllers, like the simple example does.
I already to put my EF related code in a class library and use it in an asp.net webapi project.
However I still have the following code in my webapi project.
services.AddDbContext<MyOwnDbContext>(
ops => ops.UseSqlite(connection, optionsBuilder => optionsBuilder.MigrationsAssembly("MyProject.API")));
Is there a way to decouple 'MyOwnDbContext: DbContext' class completely from webapi project (using a factory or an interface). Or this is an unnecessary concern? I just don't want to use EF related library in two projects.
I would leave it alone, since you still have to have installed Entity Framework in the entry project so that the library can use it (or hack the way through by copying files manually, but let's not get into that).
However, this is what I did in a recent project where I wanted to keep all my services in a single place, different to the Startup class:
Install Microsoft.Extensions.DependencyInjection to the project where you want your DbContext.
Add something like this:
public static class Injector
{
// you probably want to pass the connection string or an Options class here too
public static IServiceCollection Inject(this IServiceCollection services)
{
services.AddDbContext<...>(...);
return services;
}
}
Inject it, rather than the context itself:
public void Configure(IServiceCollection services)
{
services.Inject();
// and whatever else you need
services.AddMvc();
}
Like this, you do not win a lot, but you could keep going as I mentioned at the beginning.
This is an uneccessary concern. You put this into the root of your application (Startup.cs). Everything is hardwired here (Dependency Injection Container, Contexts, Logging,...).
In fact there is no better place to put it. Because the configuration of the context itself is of no concern for any layer below the application level. Your DAL/Repositories just use the already configured context and that's it.
I've a c#.net project that uses multiple 3rd party dlls. These dlls exposes interface that are used throughout the project. My question is this: These interfaces are passed to the constructor of Controller class like this:
HomeController(IClientData clientdata, IClientRecord clientrecord)
{ }
Here clientdata and clientrecord are initialized to a default value needed to start the view(produces a list of client details). I've to use these initialized data somewhere else in my project but I don't know how to get these default initialized values.
What you have seen is a very general pattern in ASP.NET MVC . Here your home controller has 2 dependencies (one class inherited from IClientData and other from IClientRecord) . These dependencies are usually injected by some DI framework .
There are some good DI frameworks available for ASP.NET MVC
Unity
Autofac
Castle Windsor
StructureMap
etc...
and they usually provide two ways to setup the dependencies -
through XML configuration files
Fluent interface (inside code)
When Fluent interface is used, a general practice is to create a separate class file inside App_Start folder and call it from global.asax (Application_Start).
I've read various other question here on the argument, most notably
Dependency Inject (DI) “friendly” library
Ioc/DI - Why do I have to reference all layers/assemblies in entry application?
and this article (and other various material).
However it's not clear to me where to place composition root in library (DLL) .NET project. The project does not belong to any specific type mentioned in the article. In desktop, console or even web application this point is instead clearly defined.
My current approach is to wrap the container, register types and re-expose the Resolve method:
class DefaultBootstrapper : IBootstrapper {
public Bootstrapper() {
_container = new XXXContainer();
RegisterTypes(_container);
}
public T Resolve<T>() where T : class {
return _container.Resolve<T>();
}
// + other _container.Resolve() overloads
private readonly XXXContainer _container;
}
Then I prevent library consumers to create root instances of the library (e.g. defining internal constructors) and hence forcing the use of a singleton factory:
class XYZFactory {
static XYZFactory() {}
private XYZFactory(IBootstrapper bootstrapper) {
_bootstrapper = bootstrapper;
}
public static XYZFactory Instance {
get { return Singleton; }
}
public ABCType CreateABCType(string param1) {
return _bootstrapper.Resolve<ABCType>(param1, _bootstrapper.Resolve<Dependency1>);
}
private static readonly XYZFactory Singleton = XYZFactory(new DefaultBootstrapper);
private readonly IBootstrapper _bootstrapper;
}
The question is, there's a better approach or a better pattern to employ for locate the composition root in a library project?
It depends on the type of library you are creating. Is your library project part of your own solution, or is it a reusable library that other developers depend upon outside your team, department, or perhaps even organization?
In the case of it being just a library project part of a solution, the library project should itself typically not contain a composition root. By definition, the composition root is a "(preferably) unique location in an application where modules are composed together". In other words, your solution would have one or multiple start-up projects (such as a MVC application, WCF service, console app), and each start-up project would get its own composition root. Layers below would not get their own composition root.
This btw does not mean that you should not prevent code duplication inside the composition roots. When there is a lot of duplication caused by a default wiring for included projects (such as DAL and BLL), you should typically extract this logic to another project. You can either do this by including part of the registration logic inside one of the projects (most likely the BLL) and let each composition root call that shared logic, or you can do this by adding a special 'bootstrapper' project for that project and the referenced projects. This bootstrapper project will only contain the registration logic. By separating this logic from the application assemblies you prevent those assemblies from needing a dependency on the used dependency injection library. It is however usually not a problem if a assembly takes a dependency on such library, as long as you make sure the application logic keeps free from taking dependencies on the container.
For reusable libraries things are usually different. In that case consumers will use your library, but you have no control over how they structure their application. You often want to supply the library in a way that it can directly be consumed by consumers, without having to do all kinds of 'complex' registration in their composition root. You often don't even know if they have a composition root at all.
In that case you should typically make your library working without a DI container. You should yourself not take a dependency on such a container, because this would drag the container in. If you do use a container, question yourself why your reusable library uses a container, and if this has to be. Perhaps you do because you designed all types around the dependency injection principle; because this makes testing easier. Don't forget that this is your problem, not the problem of your consumers. As a reusable library designer, you should hard in getting your library as usable as possible for your consumers. Please do never assume your consumers are using a DI Container. Even if they practice Dependency Injection, they might apply Pure DI rather than a DI Container.
In case you are building a reusable library, take a look at this blog post from Mark Seemann.