C
C#•4mo ago
Emberfire

Dependency injection approach for object, used only in a single method

I'm migrating an old ASP.NET 4.7.2 MVC application to ASP.NET Core and wish to learn more of the DI approach, since it's already deeply integrated into the Core framework. However, so far I've encountered some issues utilizing it. I understand DI is supposed to be used across the call chain, with every class having its dependencies injected. But what if you want to use an instance of a class only in a specific method of your current one? Are you supposed to inject it for the whole class, wasting performance on potentially heavy instantiations when it's not necessary? Here's an example;
c#
public class TestClass
{
public TestClass(ILogger<TestClass> logger)
{
}

public void DoSomething()
{
// Do work here
}

public void DoAnotherThing()
{
// Do work here
}

private void CallSomethingFromInnerClass()
{
// Problematic code
new InnerClass().DoInnerClassWork();
}
}

public class InnerClass
{
public InnerClass(ILogger<InnerClass> logger)
{
}

public void DoInnerClassWork()
{
// Do work here
}
}
c#
public class TestClass
{
public TestClass(ILogger<TestClass> logger)
{
}

public void DoSomething()
{
// Do work here
}

public void DoAnotherThing()
{
// Do work here
}

private void CallSomethingFromInnerClass()
{
// Problematic code
new InnerClass().DoInnerClassWork();
}
}

public class InnerClass
{
public InnerClass(ILogger<InnerClass> logger)
{
}

public void DoInnerClassWork()
{
// Do work here
}
}
I have a class that has many methods, each doing its own thing. Assume that class cannot be split into different smaller classes, maybe it's a controller. The inner class expects a logger with its own category. Now, I could instantiate it in the method and pass the existing logger, but that logger would have the wrong category (TestClass instead of InnerClass). I could also inject an IServiceProvider, however as I understand that is an anti-pattern and shouldn't be done when implementing DI. I could also introduce a [FromService] attribute, however that is also an anti-pattern, plus it only works for controller actions called from the environment, not private methods. What is the best approach here? Is the answer really injecting it for the whole class? What if the inner class is an ORM helper, do I need to create a DB connection every time?
18 Replies
Emberfire
Emberfire•4mo ago
P.S. One approach would be to indeed separate the method to a different object. However, doesn't that just kick the can down the road? If you would need to then inject that object to call the method, doesn't the injection still happen for the whole TestClass?
Poller
Poller•4mo ago
for me this decision is purely based on context. as a question for you to answer yourself: does TestClass honor the SingleResponsibility principle? from experiences, the thing you try to do often will be a 'no' as answer.
Emberfire
Emberfire•4mo ago
It does not, however in the context this TestClass is a controller, and to my understanding they usually serve as a hub for routing requests to business logic
Poller
Poller•4mo ago
Oh yeah you found the reason why i dont work with controllers anymore 😄
Emberfire
Emberfire•4mo ago
I could of course separate out this controller, but as per my P.S. I feel this would just kick the can down the road, as the derived new class would still need to be instantiated somewhere
Poller
Poller•4mo ago
the default usually was to inject it and take the overhead as long as its not problematic. but yeah its just what in my environments i worked in was done. is the minimal api approach not feasable? then everything is instanciated only if required(based on lifetime).
Emberfire
Emberfire•4mo ago
Unfortunately this would result in hundreds of ApiControllers, since the application is quite large, and that would make supporting it even more difficult than if I just used a IServiceProvider, for example
Poller
Poller•4mo ago
to answer this: you could. then the class would only be instanciated in that call that needs it, but then the controller scheme is unclear. we currently rebuild an api (net framework 3.5) with 450 calls as minimal api project. 0 regrets. we there can lay out the route structure in folders and use a IEndpoint interface to scan the assembly at startup and map all found classes.
Emberfire
Emberfire•4mo ago
This sounds like a better approach. However, I don't know how much of it can be implemented in my situation, since I'm trying to not have to rewrite the entire application during this migration I posted the question to StackOverflow as well and got an interesting comment about Lazy<T> injections Currently reading up on it, give me a moment
Poller
Poller•4mo ago
you can mix and match controllers with minimal api. (not a good idea, but technically possible)
Emberfire
Emberfire•4mo ago
I feel like this would be an even worse anti-pattern than just using a IServiceProvider 😄
Poller
Poller•4mo ago
yeah 🙂 its about the same place in hell.
Emberfire
Emberfire•4mo ago
Okay, so this lazy instantiation seems like a good approach to my problem. It basically works like IEnumerable<T> does for collections: it injects placeholder values for the objects needed, then instantiates them the first time they are used. This seems like exactly what I need, and doesn't add obvious drawbacks. I'm going to read up on it some more to learn if it's also considered an anti-patter, bad practice or anything similar
Poller
Poller•4mo ago
great. could you be so kind and ping me with your research results (and maybe sources then)? not something i expect to need often, but cant hurt to have in my toolbelt.
Emberfire
Emberfire•4mo ago
Absolutely. Give me a moment to respond to the guy in SO and I'll post everything here.
Poller
Poller•4mo ago
no rush.
Emberfire
Emberfire•4mo ago
Here is the question posted on StackOverflow and here is the article mentioned.
Stack Overflow
Dependency injection approach for object used only in a single method
I'm migrating an old ASP.NET 4.7.2 MVC application to ASP.NET Core and wish to learn more of the DI approach, since it's already deeply integrated into the Core framework. However, so far I've
Medium
Lazy in Dependency Injection with C# .Net Core
I am going to discuss a use case of Lazy keyword in C# in the context of Dependency Injection (DI) or Inversion of Control (IoC)
Emberfire
Emberfire•4mo ago
I'm going to be testing this solution and I'll report back with any problems I find with the approach. Thank you very much for taking the time!
Want results from more Discord servers?
Add your server