Injecting logger into middleware dependency - asp.net

I have a middleware library I intend on using in multiple projects. The middleware itself looks something like:
public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk)
{
this.next = next;
this.logger = logger;
this.sdk = agentSdk;
this.sdk.Init();
...
}
Thanks to DI, I can simply inject my logger:
// Would rather this class be internal...
public class Sdk: ISdk
{
private ILogger<Sdk> logger;
public Sdk(ILogger<Sdk> logger)
{
this.logger = logger;
}
public void Init() {
this.logger.Info(...) // Do some logging
}
The downside to this is my class needs to be registered in every ASP.Net project's Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISdk, Sdk>();
Is the best/only route? Every time I want to inject a logger into a class, I need to register that class for DI in my composition root?

There is nothing wrong in having the consumer of your library compose the dependencies for this library in the composition root. That's how dependency injection works. You could of course provide some default implementations and a custom extension method that would register those default implementations into the DI and then let the consumer simply call your extension method.

There are a few things that I feel need clarification here:
Dependency injection/inversion of control
To understand what is the benefit of dependency injection(DI) it is better to look at the principle of inversion of control(IoT) that DI implements.
In your case you want SdkMiddleware class to contain a reference to ILogger implementation. The simplest way to do this is for SdkMiddleware class to create an instance of a class that implements ILogger interface. The downside of such approach is that SdkMiddleware needs to know which class implements ILogger interface and how to instantiate it. In other words, SdkMiddleware has control over the creation of ILogger object. The inversion of control happens when the responsibility of knowing which class implements ILogger and how to create an instance of it is taken away from SdkMiddleware to some other class (dependency container in DI) and the instance if it is given to SdkMiddleware to use (through injection in DI). In this case the control over the creation of ILogger object is outside of SdkMiddleware. Since this changes the direction of control, it is called "Inversion of control".
The benefit of this approach is when you will need to provide another implementation of ILogger or change the way you create an instance of that class, you don't need to change SdkMiddleware at all.
Bootstrapping
So now that we clarified why we are using DI, lets take a look at what do we need to actually use it.
The object that creates all instances, controls which object is injected into which and gives away ready to use objects is usually called DI container or IoT container. In asp.net core "IServiceCollection services" is used as such a container. But it still needs to know how to create objects and which implementation to inject for which interface. This is where bootstrapping comes in.
In a bootstrapper class or method you need to specify how objects are built from classes and how classes relate to interfaces. As an example of the former, imagine that you need to pass a connection string for a database from your configuration to a class that creates a db connection. As for the latter, that is exactly what your line "services.AddTransient()" does.
The answer
I am sorry it took so long to get to the actual answer for your question but I wanted to provide some overview first.
Do you need to specify a relation between a class and an interface to inject logger into your class? No. Your class may not even have an interface to begin with and DI container will inject all the dependencies in it by default if you ask for an object of a class instead of an instance of an interface. You can also use or define some convention over configuration solution so that binding of classes and interfaces will happen automatically.
The bottom line is that registration of a class and the actual injection are not connected. But the code you provided is the default way to do this.

Related

Mono.Cecil: Getting Method Reference from delegate passed as Generic Parameter

I'm trying to get an understanding of which concrete types are providing the implementations of interfaces in an IOC (dependency injection) container. My implementation works fine when there are no delegates involved. However, I'm having trouble when a delegate method is passed as the type factory, as I can't get Mono.Cecil to give me the concrete type or a method reference to the factory back. I'm specifically in this case trying to build a component that can work with the IServiceCollection container for .Net ASP.Net REST APIs. I've created a 'minimised' set of code below to make it easy to explain the problem.
Consider the following C# code:
interface IServiceProvider {}
interface IServiceCollection {}
class ServicesCollection : IServiceCollection {}
interface IMongoDBContext {}
class MongoDBContext : IMongoDBContext
{
public MongoDBContext(string configName) {}
}
static class Extensions
{
public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
{
return null;
}
}
class Foo
{
void Bar()
{
IServiceCollection services = new ServicesCollection();
services.AddSingleton<IMongoDBContext>(s => new MongoDBContext("mongodbConfig"));
}
}
When successfully locating the 'services.AddSingleton' as a MethodReference, I'm unable to see any reference to the MongoDBContext class, or its constructor. When printing all the instructions .ToString() I also cannot seem to see anything in the IL - I do see the numbered parameter as !!0, but that doesn't help if I can't resolve it to a type or to the factory method.
Does anyone have any ideas on how to solve this?
Most likely your code is looking in the wrong place.
C# compiler will try to cache the conversion of lambda expression -> delegate.
if you look in sharplab.io you'll see that the compiler is emitting an inner class '<>c' inside your Foo class and in that class it emits the method '<Bar>b__0_0' that will be passed as the delegate (see opcode ldftn).
I don't think there's an easy, non fragile way to find that method.
That said, one option would be to:
Find the AddSingleton() method call
From there start going back to the previous instructions trying to identify which one is pushing the value consumed in 1 (the safest way to do that would be to consider how each instruction you are visiting changes the stack). In the code I've linked, it would be IL_0021 (a dup) of Bar() method.
From there, do something similar to 2, but now looking for the instruction that pushes the method reference (a ldftn) used by the ctor of Func<T, R>; in the code linked, it would be IL_0016.
Now you can inspect the body (in the code linked, Foo/'<>c'::'<Bar>b__0_0')
Note that this implementation has some holes though; for instance, if you call AddSingleton() with a variable/parameter/field as I've done (services.AddSingleton(_func);) you'll need to chase the initialization of that to find the referenced method.
Interestingly, at some point Cecil project did support flow analysis (https://github.com/mono/cecil-old/tree/master/flowanalysis).
If you have access to the source code, I think it would be easier to use Roslyn to analyze it (instead of analyzing the assembly).

What does it mean when saying "to be assigned something"| ASP.NET Core

I was reading a book about Learning ASP.NET Core API when I run to a part saying:
We create a private read-only field _repository that will be assigned
the injected MockCommandAPIRepo object in our constructor and used
throughout the rest of our code.
Here is some text I thought you'd better have:
Then there are some explanations related to the picture above:
Add the new using statement to reference ICommandAPIRepo.
We create a private read-only field _repository that will be assigned the injected MockCommandAPIRepo object in our constructor
and used throughout the rest of our code.
The Class constructor will be called when we want to make use of our Controller.
At the point when the constructor is called, the DI system will spring into action and inject the required dependency when we ask for
an instance of ICommandAPIRepo. This is Constructor Dependency
Injection.
We assign the injected dependency (in this case MockCommandAPIRepo) to our private field (see point 1).
And that’s pretty much it! We can then use _repository to make use of our
concrete implementation class, in this case MockCommandAPIRepo. As
I’ve stated earlier, we’ll reuse this pattern multiple times through
the rest of the tutorial; you’ll also see it everywhere in code in
other projects – take note.
Now, According to the highlighted part above in number 2, I got a little confused!
I've heard of "to be assigned by some value" before, but here, it is saying that:
that will be assigned the injected MockCommandAPIRepo object in our constructor
and as you see, there is no "by" added before the injected MockCommandAPIRepo object....
So, I have a question now. What does it mean by the highlighted part above in number 2?
Does it mean the same when we add "by" in the sentence? or not?
This is about dependency injection in Asp.Net Core. After we register service to the IOC Container, How to use it in our controller? We can inject them in controller via Constructor Injection. Once we register a service, the IoC container automatically performs constructor injection if a service type is included as a parameter in a constructor. In your question, An IoC container will automatically pass an instance of ICommandAPIRepo(MockCommandAPIRepo) to the constructor of CommandsController. Now we can use MockCommandAPIRepo in the constructor. But it can only be used in constructor, How can we use it in other method in CommandsController? Here we use:
private readonly ICommandAPIRepo _repository;
to create a global variable in CommandsController, Then in constructor, We use:
_repository = repository
assign the value of repository to _repository. Now _repository and repository has the same value, Because _repository is a global variable, So We can use _repository in other method in CommandsController. The whole process of dependency injection is done.

Register service with multiple lifetime

In a .Net Core 2.2 application, I need a version of a service as transient and a version as scoped.
For a "regular" service, I could create two different interfaces, register one as transient and one as scoped, but if both need a DbContext, it would mean I'd need to create two DbContext (yes, one can just be a wrapper) and register both, but it feels improper.
I'm using dotnet Core's default Dependency Injection framework, which I'm not that familiar with. In UnityIoC, I could easily have done that using named registrations:
//Note: Pseudo-code
void Register(IUnityContainer container)
{
container.RegisterType<IMyInterface, MyClass>(
"Transient",
new TransientLifetimeManager()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>("Transient")));
container.RegisterType<IMyInterface, MyClass>(
"PerResolve",
new "PerResolve", new PerResolvedLifetimeManager()()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>(PerResolve)));
container.RegisterType<MyDbContext>("Transient", new TransientLifetimeManager());
container.RegisterType<MyDbContext, MyClass>("PerResolve", new PerResolvedLifetimeManager());
}
Bonus points: Using the IServiceProvider, how do I ask for the transient resolution vs the scoped resolution?
The simplest way to implement this is with two interfaces as shown in the following example:
interface IMyScopedInterface
{
void Foo();
}
interface IMyTransientInterface
{
void Foo();
}
class MyClass : IMyTransientInterface, IMyScopedInterface
{
public MyClass(MyDbContext dbContext)
{
}
public void Foo()
{
}
}
and then register your class using the following:
services.AddTransient<IMyTransientInterface, MyClass>();
services.AddScoped<IMyScopedInterface, MyClass>();
You don't need to do anything special with your DbContext in order to support this. Let's walk through how the DI system would resolve these services to see if it can clarify why that's the case.
To start, the DI system tries to obtain an instance of IMyScopedInterface (typically because the DI system is trying to instantiate some other service whose constructor takes an IMyScopedInterface parameter).
Because IMyScopedInterface has been registered with a scoped lifetime, the DI system first looks within it's collection of services that have already been instantiated for the current scope to see if it has already created an IMyScopedInterface. That search comes up empty handed, so the DI system then moves on to create a new instance of MyClass.
To do that, it examines MyClass's constructor and determines that it needs a MyDbContext, so it recurses back through this same flow in order to obtain a MyDbContext.
The DI system constructs an instance of MyClass supplying the obtained MyDbContext, and then caches this MyClass object as part of the current scope so that subsequent requests for IMyScopedInterface within the same scope can receive the shared object.
The same basic flow holds true for IMyTransientInterface except that the DI system doesn't bother looking for a previously instantiated instance of the object, and after constructing the new MyClass instance it doesn't cache it at all.
What should hopefully be clear from this flow is that it doesn't really matter what the lifetime of MyDbContext is. If it's registered as transient, then every new instance of MyClass will get it's own unique instance of MyDbContext. If MyDbContext's lifetime is scoped (which is the default behavior in Entity Framework), then all instances of MyClass created within a given scope will share a single instance of MyDbContext regardless of whether the MyClass instances were instantiated for IMyScopedInterface or IMyTransientInterface.

ASP.NET Core MVC application dependency injection issue when using BaseController

Recently i tried to create a MVC application using ASP.NET Core 2.0 and i had some values defined in appsettings.json,
"MySettings": {
"WebApiBaseUrl": "http://localhost:6846/api/"
}
In order to read these values i have added
services.Configure<MySettingsModel>(Configuration.GetSection("MySettings"));
above line in ConfigureServices method in Startup.cs
and in my home controller i have added
private readonly IOptions<MySettingsModel> appSettings;
public HomeController(IOptions<MySettingsModel> app)
{
appSettings = app;
}
MySettingsModel class is just a model with property same as key define in appsettings.json.
by this method i'm able to read the value of this key.
Now my issue is that i want to use this key in many controllers so i don't want to repeat this code in every controller so what i did was i created a BaseConntroller, added its constructor and i got my values there. But when i inherit other controllers with my BaseController , it throws me an error and tells me to generate it's constructor, so basically it tells me to add constructor in every controller which is what i wanted to avoid.
How can i achieve this?
You can see the image for the error
And these are the potential fixes that it shows me.
This is just basic C# inheritance. Derived classes must re-implement constructors on base classes (at least the ones you want or need). The only exception is the empty constructor, which is implicit. In other words, you simply need:
public class HomeController : BaseController
{
public HomeController(IOptions<MySettingsModel> app)
: base(app)
{
}
And, of course, you need to change the accessibility of the base class field to protected instead of private. Otherwise, derived classes will not be able to access it.
Of course, this doesn't really save you that much. However, there's no free lunch here. Like I said, this is a limitation of C#, itself, so you have no choice. Although, it's worth mentioning, that while this can sometimes be annoying, it's actually a kind of useful feature of C#. You can look at any class and see exactly what constructors it has available, without having to trace down all its ancestors.
Actually, there is a good solution here:
https://stackoverflow.com/a/48886242/2060975
I am mostly using this method.
[Authorize]
[ApiController]
public abstract class ApiControllerBase : ControllerBase
{
private IOptions<AppSettings> _appSettings;
protected IOptions<AppSettings> appSettings => _appSettings ?? (_appSettings = (IOptions<AppSettings>)this.HttpContext.RequestServices.GetService(typeof(IOptions<AppSettings>)));
...
}
I hope it helps someone:)

Why would I want to use UnitOfWork with Repository Pattern?

I've seen a lot about UnitOfWork and Repo Pattern on the web but still don't have a clear understanding of why and when to use -- its somewhat confusing to me.
Considering I can make my repositories testable by using DI thru the use of an IoC as suggested in this post What are best practices for managing DataContext. I'm considering passing in a context as a dependency on my repository constructor then disposing of it like so?:
public interface ICustomObjectContext : IDisposable {}
public IRepository<T> // Not sure if I need to reference IDisposable here
public IMyRepository : IRepository<MyRepository> {}
public class MyRepository : IMyRepository
{
private readonly ICustomObjectContext _customObjectContext;
public MyRepository(ICustomObjectContext customObjectContext)
{
_customObjectContext = customObjectContext;
}
public void Dispose()
{
if (_customObjectContext != null)
{
_customObjectContext.Dispose();
}
}
...
}
My current understanding of using UnitOfWork with Repository Pattern, is to perform an operation across multiple repositories -- this behavior seems to contradict what #Ladislav Mrnka recommends for web applications:
For web applications use single context per request. For web services use single context per call. In WinForms or WPF application use single context per form or per presenter. There can be some special requirements which will not allow to use this approach but in most situation this is enough.
See the full answer here
If I understand him correctly the DataContext should be shortlived and used on a per request or presenter basis (seen this in other posts as well). In this case it would be appropriate for the repo to perform operations against the context since the scope is limited to the component using it -- right?
My repos are registered in the IoC as transient, so I should get a new one with each request. If that's correct, then I should be getting a new context (with code above) with each request as well and then disposing of it -- that said...Why would I use the UnitOfWork Pattern with the Repository Pattern if I'm following the convention above?
As far as I understand the Unit of Work pattern doesn't necessarily cover multiple contexts. It just encapsulates a single operation or -- well -- unit of work, similar to a transaction.
Creating your context basically starts a Unit of Work; calling DbContext.SaveChanges() finishes it.
I'd even go so far as to say that in its current implementation Entity Framework's DbContext / ObjectContext resembles both the repository pattern and the unit of work pattern.
I would use a simplified UoW if i wanted to push context's SaveChanges away from the repositories when they share the same instance of context across one web request.
I imagine you have sth like Save() method on your repositories that looks similiar to _customObjectContext.SaveChanges(). Now lets assume you have two methods containing business logic and using repos to persist changes in DB. For the sake of simplicity we'll call them MethodA and MethodB, both of them containing a fair amount of logic for performing some activities. MethodA is used separately in the system but also it is called by MethodB for some reason. What happens is MethodA saves changes on some repository and since we are still in the same request changes made in MethodB, before it called MethodA, will also be saved regardless of whether we want it or not. So in such case we unintentionally break the transaction inside MethodB and make the code harder to understand.
I hope i described this clear enough, it wasn't easy. Anyway other than that i cannot see why UoW would be helpful in your scenario. As Dennis Traub pointed quite correctly ObjectContext and DbContext are in fact an implementation of a UoW so you'd be probably reinventing the wheel while implementing it on your own.
The ObjectContext/DbContext is an implementation of the UnitOfWork pattern. It encapsulates several operations and makes sure they are submitted in one transaction to the database.
The only thing you are doing is wrapping it in your own class to make sure you're not depending on a specific implementation in the rest of your code.
In your case, the problem lies in the fact that your Context shouldn't be disposed of by your Repository. The Repository is not the one that instantiates the Context, so it shouldn't dispose of it either. The UnitOfWork that encapsulates multiple repositories is responsible for creating and disposing the Context and you will call a Save method on your UnitOfWork.
Code can look like this:
using (IUnitOfWork unitOfWork = new UnitOfWork())
{
PersonRepository personRepository = new PersonRepository(unitOfWork);
var person = personRepository.FindById(personId);
ProductRepository productRepository = new ProductRepository(unitOfWork);
var product= productRepository.FindById(productId);
p.CreateOrder(orderId, product);
personRepository.Save();
}

Resources