I started a new class library project and I want to use Dependency Injection for services and DbContext, etc.
However there is no Program.cs file.
Where should I configure the DI interfaces and classes? Do I need to add an empty Program.cs?
for example, if you have a class library as a business access layer. you can add a class in the root with the name DependencyInjection as the following
public static class DependencyInjection
{
public static void AddApplication(this IServiceCollection service)
{
service.AddScoped<IOrgSettingsService, OrgSettingsService>();
service.AddScoped<IIdentity, IdentityService>();
service.AddScoped<ILdapAuthenticationService, LdapAuthenticationService>();
service.AddScoped<IOrgAuthenticationService, OrgAuthenticationService>();
service.AddScoped<IVacanciesService, VacancyService>();
// assemblers
service.AddScoped<IVacancyAssembler, VacancyAssembler>();
}
}
and register it in startup class as the following
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplication();
}
dependency injection used for whole application.Main application injects services to all assemblies. for example, dbcontext inject from main application to your assembly.You should not define dependency instance for each assembly separately and locally
Related
In my Asp.net Core 5 API Project
I have a serviceLayer that the controller uses, to get data from a third layer called dataLayer.
I want to use the service layer as a DLL in different projects.
This ServiceLayer Contain dependency Injections like that :
namespace ServiceLayer
{
public class UserService : IUserService
{
IUserRepository userRepository; // (From DataLayer)
public UserService(IUserRepository repository) : base(repository)
{
this.userRepository = repository;
}
public Users GetAllPersonsById(int id)
{
return userRepository.GetById(id);
}
}
public interface IUserService : IService<Users>
{
Users GetAllPersonsById(int id);
}
How can I use the method GetAllPersonsById with the DLL ServiceLayer
can I use it because the dependency Injections
As soon as you reference the DLL / project you can use all classes the same ways as if they were in the project.
To use a class as a service:
Provide the service
Inject the service
There's a lot of documentation available, so I'll keep this short:
// provide in startup.cs
services.AddTransient<IUserService, UserService>();
// Inject where you need it
MyConstructor(IUserService userService) {}
See https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0
Provide Extension Method
If we take a look at other libs, most of them provide a method to setup the services.
Example: Entity framework core
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(...));
}
So you could:
In your lib, create an extension method for IServicesCollection that adds all services of your lib.
In the consuming project, call services.AddMyLibServices().
This could look like so:
public static class ServicesConfiguration
{
public static void AddDataLayer(this IServiceCollection services)
{
services.AddTransient<IUserService, UserService>();
// ... same for all services of your lib
}
}
Here's a tutorial with more details:
https://dotnetcoretutorials.com/2017/01/24/servicecollection-extension-pattern/
Lamar service registries
An optional and alternative approach are service registries. It's very similar to the extension methods but uses a class to do the setup. See https://jasperfx.github.io/lamar/documentation/ioc/registration/registry-dsl/
Composition Root
You may want to read about the composition root pattern, e.g. What is a composition root in the context of dependency injection?
In a simple app, your startup.cs is your composition root. In more complex apps, you could create a separate project to have a single place to configure your apps services.
Create the DLL
There are two ways to create the DLL:
As a project in your solution (so your solution has multiple projects, each will result in a separate DLL)
As a separate solution and as nuget package
I am doing a project in .net core
and always adding Interfaces and Services implement that Interfaces
public interface IDBContainer{
...
}
public class DBContainer : IDBContainer{
...
}
and i inject them in the startup
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IDBContainer, DBContainer>();
}
or using extension method adding them
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
{
services.AddTransient<IDBContainer, DBContainer>();
return services;
}
and in startup
[..]
services.AddInfrastructure();
but that is the problem i has to inject each one myself as interface and service
in the extension method or in the startup class
is there away to add the interface and implementation for it automatically. and there is another thing the interfaces and class is in another project assembly in the same solution???
and there is no problem to use other library if it can do it like AutoFac or something
Have you tried https://github.com/khellang/Scrutor ?
As far as I know AutoFac can also be used with some extra work documented here https://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html
While I personally prefer EXPLICIT IoC registrations.
Here is a "autoscan" library.
NetCore.AutoRegisterDi
https://www.nuget.org/packages/NetCore.AutoRegisterDi/
https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/
How to NetCore.AutoRegisterDi works The NetCore.AutoRegisterDi library
is very simple – it will scan an assembly, or a collection of
assemblies to find classes that a) are simple classes (not generic,
not abstract, not nested) that have interfaces and b) have an
interface(s). It will then register each class with its interfaces
with the NET Core DI provider.
I have a Web API implementation in ASP.NET Core and I'd like to use the included Dependency Injection.
In addition I have late binded assemblies, where I have to load a Type and create an instance of it, which can have dependencies to the main application.
I am trying to load dynamic resources from Assemblies I do not know while startup. So I am using Assembly.Load("name") and look up factory types, that give me the resource reader implementation of the Assembly.
So I know the type I need to create an instance of, but I cannot register it to the IServiceCollection and therefore cannot create instances with the ServiceProvider.
So I tried to register my found types to the IServiceCollection which was provided by the framework. For what I registered the ServiceCollection within itself.
// Within Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServiceCollection>(services);
}
// A service to register new dependencies later on
public class ServiceRegistrationService : IServiceRegistrationService
{
public IServiceCollection Services { get; }
public IServiceRegistrationService RegisterSelfTransient(Type type)
{
Services.AddTransient(type);
return this;
}
}
After calling this method like:
ServiceRegistrationService.RegisterSelfTransient(typeof(MyConcreteType));
I'd expect the IServiceProvider to resolve a new instance of my type.
Is there a way to register services after leaving the ConfigureServices(IServiceCollection services) method?
After execution of WebApplicationBuilder.Build() in Program.cs's top-level statements, the IServiceCollection turns to read-only one:
public IHost Build()
{
...
// Prevent further modification of the service collection now that the provider is built.
_serviceCollection.MakeReadOnly();
...
}
So it seems no further changes could be introduced after that.
I see in many MVC examples how to register your interfaces in the ConfigurationServices method of the Startup Class. This is fine when you have your code all written within the MVC app, but in the 'Real World' this wouldn't necessarily be the case.
I have a class library project in the form
public class MyService : IMyService
{
private readonly IMyRepository _myRepository;
public MyService(IMyRepository myRepository)
{
_myRepository = myRepository;
}
.......
Now in my controller I have a constructor of the form:
public HomeController(IConfigurationRoot config, IMyServcie myService)
{
......
The problem is, the MyService interfaces have not been registered with the DI Container and I don't really want to bloat the ConfigurationServices method with loads of services.AddScoped<interface,class>() lines of code for my other layers.
What do I need to do in my other layers (Repository and Service) to first register them here (both are .NET Core class library projects) and then wire those containers into the parent container?
ConfigurationServices is your composition root so that's where you register you services. The bloat has to go somewhere. You can create an extension method in your other layers and targets IServiceCollection and then populate as needed. They technically are not first registered there. they are registered in the composition root when you apply the extension method against IServiceColection
Your other layers would have to reference Microsoft.Extensions.DependencyInjection.Abstractions in order to have access to the IServiceCollection interface.
IMO I don't think these extension methods need to be in your service or repository layers. Those layers don't need to know anything about how they are composed. You can just as easily put them in your composition root in another class and call them just as shown above if the end goal is to make the startup class cleaner. Or put in a separate extension project which is specifically for targeting .net core's DI framework.
Service Extension Layer
public static IServiceCollection AddMyServices(this IServiceCollection services) {
services.AddScoped<IMyService, MyService>();
//...add other services
}
Repository Extension Layer
public static IServiceCollection AddMyRepositories(this IServiceCollection services) {
services.AddScoped<IMyRepository, MyRepository >();
//...add other services
}
And then in your composition root ConfigureServices
public void ConfigureServices(IServiceCollection services) {
//...other code
services
.AddMyServices()
.AddMyRepositories();
//...other code
}
UPDATE
based on comment you could just as easily call the services.AddMyRepositories() in the AddMyServies extension method as opposed to the main project itself
public static IServiceCollection AddMyServices(this IServiceCollection services) {
services.AddMyRepositories();
services.AddScoped<IMyService, MyService>();
//...add other services
}
And then in your composition root, ConfigureServices will only need to call the AddMyServices
public void ConfigureServices(IServiceCollection services) {
//...other code
services.AddMyServices();
//...other code
}
I am using autofac in my web api to register log4net . It is working fine in controller but how can i use same log4net instance for common library project classes in same solution.
I have used below code for registering log4net using autofac in web api.
// IOC Container Setup uisng Autofac
var builder = new ContainerBuilder();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.Register(c => LogManager.GetLogger(typeof(Object))).As<ILog>();
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModule<AMLWebApiModule>();
builder.RegisterFilterProvider();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
I am using logger as a property in common library project.
public ILog logger { get; set; }
when i tried to log message it is giving below exception.
Object reference not set to an instance of an object.
Please advise how can i use log4net in common library project.
So there are two approaches to make this work
1) Inject ILog in the class library project
2) Resolve the Ilog object in the class library project
I would go for option 1) and will register all my components in autofac to take full advantage of DI and keep each component independent.
Example Code,
Create a contract for the class library project example
public interface Ilibrary
{
string GetName();
}
public class Library : Ilibrary
{
private ILog _log;
public Library(ILog log)
{
_log = log;
}
public string GetName()
{
_log.Debug("log message");
return "test";
}
}
then either create a module in the class library project and register that module in your application start.
public class DomainModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<Library>()
.AsImplementedInterfaces()
.SingleInstance();
}
}
Or you can directly register too if you have access to the concert implementation just by doing this in your application start.
builder.RegisterType<Library>()
.AsImplementedInterfaces()
.SingleInstance();
Since you are using Logger as a property in your common library project, you can just decorate/annotate that property with [Dependency] attribute. This is called property injection. I am not sure if you have to have to do extra configuration for property injected dependencies in autofac but you can try if not you can search it.