In Web API 2.2: How to use the dependency injector when needed? - asp.net

I have a question for the article, which probably many of us have read: Dependency Injection in ASP.NET Web API 2.
Let's assume, that the ProductRepository at some later point in time needs to delegate to some other service. How should ProductRepository request the concrete instance from the dependency injector at that later time as it is a bad practice to inject the dependency injector itself into the ProductRepository?

You can inject the new service inside the ProductRepository just like you injected the IProductRepository into ProductsController.
public class ProductRepository : IDisposable
{
private readonly IOtherService m_OtherService;
public ProductRepository(IOtherService other_service)
{
m_OtherService = other_service;
}
...
}
If you register IOtherService successfully in the container, the container would be able to create ProductRepository and ProductsController successfully.
If it is a problem for you to have the OtherService created everytime (maybe you will not use it all the time), you can use the factory pattern. For example:
public interface IOtherServiceFactory
{
IOtherService Create();
}
public class ProductRepository : IDisposable
{
private readonly IOtherServiceFactory m_OtherServiceFactory;
public ProductRepository(IOtherServiceFactory other_service_factory)
{
m_OtherServiceFactory = other_service_factory;
}
...
}
Now, you can create an instance of OtherService only when you need it.
You have to create an implementation of IOtherServiceFactory and register it with the container.

Related

How do i inject a service to another service in Blazor?

I have DataService and StateContainer.
DataService is responsible to obtain and provide data with respect to state changes. StateContainer is responsible as states changes, it registeres as a singleton.
I want DataService can access StateContainer public property. such that it could provide the data accordingly, How may I do so? How should I register DataService?
Just register your DataService in the DI System
builder.Services.AddSingleton<DataService>();
Now you should be able to Access the StateCointainer via DI if you inject it via the Constructor.
public class DataService
{
private readonly StateContainer _stateContainer;
public DataService(StateContainer stateContainer)
{
_stateContainer = stateContainer;
}
}

How do I instantiate class with dependency injection in .net core 5 or 6?

In a .net core 5 or 6 api, if I have a dependency:
services.AddScoped<IMyDependency>((svc) =>
{
return new MyDependency(appSettings.ConnectionStrings.MyDB);
});
and I have a class that uses the dependency:
public class MyClass
{
public MyClass(IMyDependency dependency)
{
...
}
}
How do I instantiate the class so that the dependency is injected into the constructor? In a controller, this is done for me when the controller is instantiated. How do I do it for my own classes?
I can use services.GetServices explicitly, but I think that is frowned upon.
I can use services.GetServices explicitly, but I think that is frowned
upon.
Yes, this is the documented way to do it:
Services and their dependencies within an ASP.NET Core request are
exposed through HttpContext.RequestServices.
Source
HttpContext.RequestServices is of type IServiceProvider which offers the GetService method.
But it is also adviced not to do it:
Avoid using the service locator pattern. For example, don't invoke
GetService to obtain a service instance when you can use DI instead
Source
This won't be done by default. If you are trying to use something that is injected into the request pipeline, you would have to pass that injected value in the controller and pass it on to the constructor.
public class HomeController : Controller
{
private IMyDependency _dependency;
public HomeController(IMyDependency dependency)
{
_dependency = dependency;
}
[Route("")]
public IActionResult Index()
{
MyClass myclass = new MyClass(_dependency);
....
return View(myclass.stuff);
}
Add the class and its dependencies to the service collection, then inject it into your methods or use the IServiceProvider GetRequiredService
eg.
public class MyClass
{
public MyClass(IMyDependency dependency)
{
...
}
}
...
startup.cs
services.AddScoped<IMyDependency, MyDependency>();
services.AddScoped<MyClass>()
...
[Route("home")]
public IActionResult Index([FromServices]MyClass myClass)
{
var result = myClass.DoStuff();
....
return View(result);
}

Dependency injection in my singleton class .NET Core

I'm having trouble injecting the dependency I pass into the constructor of my Asegurador class.
When I want to instantiate, _instance = new Asegurador(); I don't have the parameter required by the constructor (IGeneralRepository), how can I solve this problem?
Note that my Asegurador class is a singleton.
private Asegurador(IGeneralRepository generalRepository)
{
_token = GetTokenAsync().Result;
_repository = generalRepository;
}
public static Asegurador Instance
{
get
{
if (_instance == null)
{
_local = System.Environment.GetEnvironmentVariable("SEGUROS_LOCAL") ?? "local";
_instance = new Asegurador();
}
return _instance;
}
}
When using a DI container you can (and should) let it take care of handling the Lifetime of a dependency.
.Net core's dependency injection lets you define 3 different lifetimes for your services (Docs):
Transient: a transient service is recreated each time it is injected
Scoped: a scoped service is created once for each request
Singleton: a singleton is created once in the whole application lifetime.
The best approach to achieve what you are trying to do is the following:
Amend your Asegurador class so that it has a public constructor and get rid of the static Instance property
public class Asegurador {
public Asegurador(IGeneralRepository generalRepository)
{
_token = GetTokenAsync().Result; //I know too few about it but I would try to pass it as a dependency as well
_repository = generalRepository;
}
}
instead of calling Asegurador.Instance inject the dependency in the client class
public class IUseTheAsegurador {
private Asegurador _asegurador;
public IUseTheAsegurador(Asegurador asegurador)
{
_asegurador = asegurador;
}
}
Register all in the DI in your Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<Asegurador>();
services.AddScoped<IUseAsegurador>(); //This can be Singleton or Transient as well, depending on your needs
...
}
I (a lot of people actually :D) prefer this approach because it leaves the responsability of guaranteeing a single instance to the DI and also because lets you write unit tests for the client class (IUseTheAsegurador in the example) in an easier way.

what is the best way to inject multiple interface in Constructor Injection

On an ASP.NET MVC solution I have a Service layer which contains services for each Model. For example for DocumentModel I have Document Service which is instantiated by a UoW class which acts like a factory and does the save:
public class UnitOfWork : IUnitOfWork
{
private IRepositoryFactory _repositoryFactory;
public UnitOfWork()
: this(new RepositoryFactory())
{
}
public UnitOfWork(IRepositoryFactory repositoryFactory)
{
_repositoryFactory = repositoryFactory;
}
private IDocumentService _DocumentService;
public IDocumentService DocumentService
{
get
{
if (_DocumentService == null)
{
_DocumentService = new DocumentService(_repositoryFactory.DocumentRepository);
}
return _DocumentService;
}
}
}
Now say I need to be able to access 2 or 3 other repositories from DocumentService. What is the best way to inject this new repositories? Add them in the constructor( which if I need to add yet another repository can become cumbersome) or should I just inject the repository factory (IRepositoryFactory) which will allow me to access in DocumentService any repository I may need.

How do I Inject Dependencies with Ninject, where instances are deserialised from json

This is my first try using DI, I've chosen ninject for it's reportedly easy learning curve, and have this question.
I'm creating objects like this:
var registrants = JsonConvert.DeserializeObject<List<Registrant>>(input);
I currently have this constructor for Registrant
[Inject]
public Registrant(IMemberRepository memberRepository)
{
_memberRepository = memberRepository;
}
What is the best way to have the repository dependency be injected into the deserialized object(s) using Ninject?
You can't use constructor injection with objects that are not created by Ninject (e.g. deserialized objects). But you can use property injection. Just call kernel.Inject(obj)
One question that remains is why you want to inject those objects. Normally, you don't want to use depedency injection on data container objects. In a proper design they don't have any dependency on services. The operations that need to be done on the services are done by the owner of the data container objects. I recommend to consider a refactoring of your design.
Assuming you're using Ninject V2, and you're using it in the context of an ASP.NET app, you should be using Ninject.Web to do the hookups.
Then you set up a Global class with the Factory Method support hooked in:
public class Global : NinjectHttpApplication
{
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel( new Module() );
kernel.Components.Add( new FuncModule( ) );
return kernel;
}
}
that registers the module that will Bind IMemberRepository to something:
public class Module : NinjectModule
{
public override void Load()
{
Bind<IMemberRepository>().To<MemberRepository>();
}
}
and the page wires up like this:
public class ThePage : PageBase
{
readonly Func<Registrant> _createRegistrant;
public ThePage( Func<Registrant> createRegistrant )
{
_createRegistrant = createRegistrant;
}
private void OnCreateRegistrant()
{
var newRegistrant = _createRegistrant();
}
}
NB not 100% sure if constructor injection is supported for Web Forms pages or wheter the above needs to drop to property injection... anyone?
(assuming the classes you have are as follows:)
public class MemberRepository : IMemberRepository
{
}
public interface IMemberRepository
{
}
public class Registrant
{
private readonly IMemberRepository _memberRepository;
public Registrant( IMemberRepository memberRepository )
{
_memberRepository = memberRepository;
}
}

Resources