Home > Net >  Dependency Injection in nested classes
Dependency Injection in nested classes

Time:10-03

Am new into using dependency injection and interfaces, and i have run into a situation where i can't figure out how to solve.

Im building a console app, where i need to use serilog, and get settings from the appsettings.json

I have 3 .cs files.

Program.cs:

static void Main(string[] args)
{
    Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

    var builder = new ConfigurationBuilder();

    BuildConfig(builder);

    Log.Logger = new LoggerConfiguration()
        .ReadFrom.Configuration(builder.Build())
        .Enrich.FromLogContext()
        .CreateLogger();

    Log.Logger.Information("Starting Datacollection");

    var host = Host.CreateDefaultBuilder()
        .ConfigureServices((context, services) =>
        {
            services.AddTransient<IMyClass, MyClass>();
        })
        .UseSerilog()
        .Build();

    var svcMyClass = ActivatorUtilities.CreateInstance<MyClass>(host.Services);



    svcMyClass.MyMethod();

}

IMyClass.cs:

public interface IMyClass
{
    void MyMethod();
}

and MyClass.cs:

public class MyClass : IMyClass
{
    private readonly ILogger<MyClass> _log;
    private readonly IConfiguration _config;

    public MyClass(ILogger<MyClass> log, IConfiguration config)
    {
        _log = log;
        _config = config;
    }

    public void MyMethod()
    {
        
        //Do something

    }
}

All of this works great. And i can use _log and _config to access Serilog and the config from within MyClass.

However now need to call methods from a new Class (MyClass2) from within MyMethod, and the Methods in MyClass2 needs to be able to use Serilog and the config file.

What is the best way to do this?

CodePudding user response:

That still depends on how you implement solution.

  1. If you plan to implement IMyClass2 interface and MyClass2 implement this. Also this IMyClass2 is being registered in service collection then.
public interface IMyClass2
{
   void Test();
}

public class MyClass2 : IMyClass2
{
private readonly ILogger<MyClass> _log;
private readonly IConfiguration _config;

public MyClass2(ILogger<MyClass> log, IConfiguration config)
{
    _log = log;
    _config = config;
}

  public void Test() {}
}
  • Now in MyClass you can inject IMyClass2 as dependency to MyClass and MyClass2 will take care of its dependency for logger and configuration.

  • From my point of view this is good way as you should not have to worry about MyClass2 dependency.

  1. Another things is that if you don't want to do dependency way then you can directly create instance of MyClass2 and pass dependency but in that case you have to pass either in method call or needs to use ActivatorUtilities.

Note : This is completely my opinion and it may vary.

CodePudding user response:

I think you have to add your class to asp.net services and then inject it instead of creating an instance of it . In first step, if you using older version of dotnet, open your Startup.cs file and add :

builder.Services.AddScoped<IMyClass, MyClass>();

and if you are using the newer version, you should add this service in your Program.cs (Startup and Program classes are merged in new version of dotnet)

after that when ever you

public class Class 
{
    private readonly IMyClass _class;

    public Class(IMyClass myClass)
    {
        _class = myClass;
    }
}

And you can call your method where ever you want like this : _class.MyMethod();

CodePudding user response:

You inject MyClass2 into MyClass to gain access to the methods of MyClass2.

To access Serilog and config files in MyClass2, you will have to separately inject them into that class, which would then allow MyClass2 methods to take advantage of them.

In conclusion, just because you've injected MyClass2 into a class that has Serilog (or any other dependency) injected, it doesn't mean that MyClass2 can also use those dependencies.

You will have to separately inject.

public interface IMyClass2
{
    void Process();
}

public class MyClass2 : IMyClass2
{
    private readonly ILogger<MyClass> _log;
    private readonly IConfiguration _config;

    public MyClass(ILogger<MyClass> log, IConfiguration config)
    {
        _log = log;
        _config = config;
    }

    public void Process()
    {
        ...
    }
}

public class MyClass : IMyClass
{
    ...
    private readonly IMyClass2 _myClass2;
    
    public MyClass(..., IMyClass2 myClass2)
    {
        ...
        _myClass2 = myClass2
    }

    public void MyMethod()
    {
        var result = _myClass2.Process();
    }
}

  • Related