Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection IOption class library

I have a class library where I want to access a Connectionstring from appsettings.json.

appsettings.json :

"DatabaseSettings": {
    "ConnectionString": "Server=.;Database=Test;Trusted_Connection=True;"
  },

In startup.cs I have the following code:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
    services.AddOptions();

    services.AddTransient<IConnectionOption, Class1>();
}

And in class library

IConnectionOption.cs

public interface IConnectionOption
{
    void ReadValue();
}

Class1.cs

public class Class1 : IConnectionOption
{
    private readonly DatabaseSettings test;

    public Class1(IOptions<DatabaseSettings> dbOptions)
    {
        test = dbOptions.Value;    
    }    

    public void ReadValue()
    {
        var r = test;
    }
}

Now from index.cshtml I want to Invoke the class Library Class1

public class IndexModel : PageModel
{
    public void OnGet()
    {
        Class1 test = new Class1();
        test.ReadValue();
    }
}

But of course that doesnt work since there are no Constructor taking zero parameters, I don´t think I should add IOptions as an parameter. But how do I invoke the class library to read the connectionstring? (When I get this to work I will of course read data and return instead of the connectionstring). I have looked at several examples including net core 2.1 Dependency injection But I don´t understand how to use the class library directly, Is it necessary to use an controller ?!

like image 303
user3197410 Avatar asked Sep 20 '25 18:09

user3197410


2 Answers

If DatabaseSettings is accessible to the class library, there really is not much need for tightly coupling Class1 library to IOptions, which is more framework related.

Ideally Class1 can explicitly depend on DatabaseSettings via explicit constructor injection

public class Class1 : IConnectionOption {
    private readonly DatabaseSettings test;

    public Class1(DatabaseSettings settings) {
        test = settings;    
    }    

    public void ReadValue() {
        var r = test;
        //...
    }
}

then in Startup, the dependency can be extract from configuration and registered with the DI container

public void ConfigureServices(IServiceCollection services) {
    var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
    services.AddSingleton<DatabaseSettings>(settings);    
    services.AddTransient<IConnectionOption, Class1>();
}

That way when ever Class1 is resolved, the container will know how to inject the DatabaseSettings dependency.

Another option could have also been to use the factory delegate

public void ConfigureServices(IServiceCollection services) {
    var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
    services.AddTransient<IConnectionOption, Class1>(_ => new Class1(settings));
}

That way, when the IndexModel depends on IConnectionOption for injection.

public class IndexModel : PageModel {
    private readonly IConnectionOption connectionOption;

    public IndexModel(IConnectionOption iConnectionOption) {
        connectionOption = iConnectionOption;
    }

    public void OnGet() {
        connectionOption.ReadValue();
        //...
    }
}

the proper dependency will be injected when the page model is initialized.

like image 115
Nkosi Avatar answered Sep 22 '25 09:09

Nkosi


You are using Dependency Injection but only halfway. This is what you are missing:

  1. Register the service in the container (I'm going to assume a better name for Class1):

    services.AddScoped<IConnectionOption, DatabaseConnectionOption>();
    
  2. Make the page receive the service:

    public class IndexModel : PageModel
    {
        private readonly IConnectionOption _IConnectionOption;
    
        public IndexModel(IConnectionOption iConnectionOption)
        {
            _IConnectionOption = iConnectionOption;
        }
    
        public void OnGet()
        {
            _IConnectionOption.ReadValue();
        }
    }
    
like image 26
Camilo Terevinto Avatar answered Sep 22 '25 09:09

Camilo Terevinto