How to create a class without constructor parameter which has dependency injection

10,251

Solution 1

But when i create an instance by using new keyword, dependency injection doesn't work.

That’s fundamentally how dependency injection works.

With dependency injection, you are simply not supposed to new up new objects. That’s the whole point of dependency injection and inversion of control. Instead of creating objects and managing those objects’ dependencies, you are depending on the framework to give you the dependencies you need without having you to care about where they actually come from and how they are constructed properly. So you are moving the responsibility to create the object up to the caller.

If you find yourself in need to create an object that has a dependency, then this is a clear sign that you are doing it wrong. A common reason for this is that you want to create the object in order to manage its lifetime, or because it is actually a data object that just happens to have some operations that needs other dependencies to work (e.g. an entity that has a “save” method). In the first case, you simply don’t do it like that. You just depend on it and let the framework manage the lifetime; if it has an incorrect lifetime, then you should reconfigure it with the DI container.

In the latter case where you have a data object with operations, you should split this up. You should just have a data object, without any logic, and then inject some manager service that is able to perform the operation on that data object for you.

For example in ASP.NET Core Identity, you have the User object which is just a normal entity without any logic. In order to e.g. add user roles or change the password, you rely on the user manager which you can inject. So the User object itself is without any dependencies.

I’d generally suggest you to read the dependency injection chapter of the ASP.NET Core documentation to understand how dependency injection works and how it is supposed to be used within the framework.

Solution 2

As mentioned in the comments, it is not clear what you trying to achieve, but in order to do DI in .Net Core you have to create an interface IMyClass, then let your class implement that interface,

public interface IMyClass {
   void SampleMethod();
}

public class MyClass : IMyClass
{
    ILoginTokenKeyApi _loginTokenKeyApi;

    public MyClass(ILoginTokenKeyApi loginTokenKeyApi)
    {
        _loginTokenKeyApi = loginTokenKeyApi;
    }

    public void SampleMethod()
    {
        // method logic goes here...
        var xx = _loginTokenKeyApi.WhatEver;
    }
}

then register ILoginTokenProvider and IMyClass in startup.cs

services.AddTransient<ILoginTokenProvider, LoginTokenProvider>();
services.AddTransient<IMyClass, MyClass>();

finally inject IMyClass where you need it:

public class IndexModel : PageModel {

    private readonly IMyClass _myClass;

    public IndexModel(IMyClass myClass)
    {
        _myClass = myClass;
    }

    public void OnGet()
    {
       _myClass.SampleMethod();
    }
}

btw, it is also possible to register and inject MyClass without implementing IMyClass interface, but I prefer to follow basic programming principals :)

Share:
10,251
canmustu
Author by

canmustu

Software Engineering Team Lead at Hicelerate

Updated on June 04, 2022

Comments

  • canmustu
    canmustu almost 2 years

    I have added the dependency injections to the project. But when i create an instance by using new keyword, dependency injection doesn't work.

    public class MyClass
    {
        ILoginTokenKeyApi _loginTokenKeyApi;
    
        public MyClass(ILoginTokenKeyApi loginTokenKeyApi)
        {
            _loginTokenKeyApi = loginTokenKeyApi;
        }
    
        ...
    }
    

    When i try to create an instance of MyClass, it wants a parameter to be constructed naturally.

    Just like this :

    MyClass mc = new MyClass(); // ERROR, it wants a parameter (but it is what i want)
    

    I have to do :

    MyClass mc = new MyClass(new LoginTokenKeyClass()); // this is not a good code for me
    

    How i create an instance of MyClass without parameter because it has dependency injected.

  • poke
    poke over 5 years
    Not my downvote but this answer does not cover the fundamendal issue OP has when attempting to use dependency injection. Property injection will not solve this at all, and even with property injection you will not be able to new up an object (which is what OP wants to do).
  • poke
    poke over 5 years
    You are not required to create and implement interfaces in order to use dependency injection properly. Switching to interfaces will not help OP in what they are trying to achieve, which is creating an object with new while having the dependencies resolved automatically. That just doesn’t work with dependency injection.
  • LazZiya
    LazZiya over 5 years
    @poke, I already mentioned that creating interface is not necessary for DI, but the question itself was not clear enough to explain the problem, so I tried to offer a possible solution.
  • Prateek Shrivastava
    Prateek Shrivastava over 5 years
    @poke - Our Answer/Post is for the first version of the Question that OP posted. The question has been modified. Also, OP can remove the Constructor Injection (add Param Less constructor) - that will allow him to new up the object. Also, as I advised they can add GetObject() call for fetching the Dependency.
  • Steven
    Steven over 5 years
    "With dependency injection, you are simply not supposed to new up new objects.". I understand what you are trying to say here, but this is not completely accurate. It is completely fine to new up dependencies, as long as you do this inside the start-up path of your application, a.k.a. the Composition Root. DI does not require the use of a DI Container, a practice commonly referred to as Pure DI. Apart from that, I agree with you.
  • poke
    poke over 5 years
    @Steven Sure, in that case, that would be perfectly fine. From the context of the question, this is ASP.NET Core which does have a (mandatory) DI container and as such OP is attempting to do that within a dependency (since you simply don’t have access to the composition root like that). – But yeah, your comment is completely valid although I do think that it goes a bit too deep considering OP’s atttempts :)
  • Steven
    Steven over 5 years
    It is a common misunderstanding that using a DI Container is mandatory in ASP.NET Core. This is not the case.
  • poke
    poke over 5 years
    @Steven I’d be interested to see how to set it up without a DI container when the full framework uses dependency injection to compose its components. But I honestly doubt that you will be able to do this without a container unless you are talking about composing hundreds of (internal) dependencies manually.
  • Steven
    Steven over 5 years
    Chapter 7.3 of my book actually describes in detail how to apply Pure DI in ASP.NET Core. You can see a short demonstration in this repository. When to choose a DI Container over Pure DI, however, is a more complicated question. This is something that is discussed in chapter 12.
  • poke
    poke over 5 years
    @Steven Sorry, but no, that is not an example of ASP.NET Core without a dependency injection container. Yes, you are avoiding the existing container for your own (two) components but the project is still using the default DI container and you are in fact using it in order to set up your CompositionRoot as well. – So if that’s your example, then I’ll have to stand by my point that you cannot really use ASP.NET Core practically without a DI container.
  • Steven
    Steven over 5 years
    even though the ASP.NET Core framework might use something that resembles a container (I typically refer to that thing as "the configuration system"), you are not required to use it to build up your application components, and this is actually important. The choice between using a DI Container or Pure DI must be consciously made, especially because that built-in "configuration system" is really limited. Practicing Pure DI has many advantages, even when the framework uses reflection to build its internal components.
  • poke
    poke over 5 years
    @Steven Unless you reconfigure it, the framework will use Microsoft.Extensions.DependencyInjection which is a DI container. – In any way, this discussion is derailing quite a bit now and is no longer relevant to the actual question.