What to pass to class with IConfiguration Constructor?

Viewed 2841

I have a class that contains a method that uses some database connection strings and instead of hard coding them, I want to pull them from my appsettings.json file. So, following others who have done similar things, I created a constructor with an IConfiguration parameter. I am attempting to use the SearchOfficer method in a Blazor Page's base class, to do so I tried to make a new instance of Search but couldn't figure out: what should I pass to the constructor?

The Class with the Method:

public class Searches
{
    private readonly IConfiguration _config;

    public Searches(IConfiguration configuration)
    {
        _config = configuration;
    }
           
    public async Task<List<NameScore>> SearchOfficer(string Input)
    {            
        //processy stuff

        //Querying stuff
        DataAccess data = new DataAccess();
        string sql = "SELECT IdOfficer, Name FROM officers";
        List<FirstLoadOfficer> Names = await data.LoadData<FirstLoadOfficer, dynamic>
                                       (sql, new { }, _config.GetConnectionString("DataDB"));
      
        //Sorting and Comparing stuff
        return SortedNames;        
    }
}

How I am attempting to use it:

 Searches searches = new Searches(/*what should I put here?*/);
 SimilarPeople = await searches.SearchOfficer("Input Name");
1 Answers

Avoid injecting IConfiguration (code smell). Consider explicitly injecting what is actually needed in the target class.

You are not following what was shown in the linked article.

It suggests creating a model to hold the information needed, which in this case could look something like

public class ConnectionStrings
    public string DataDB { get; set; }  
}

Configure the model in startup

//...

services.AddOptions();  
  
//Configure Option using Extensions method  
services.Configure<ConnectionStrings>(Configuration.GetSection("ConnectionStrings")); 

//...

And refactor the target class to depend on the model via dependency injection and the options pattern

public class Searches : ISearches {
    private readonly ConnectionStrings connectionStrings;

    public Searches(IOptions<ConnectionStrings> options) {
        connectionStrings = options.Value;
    }
           
    public async Task<List<NameScore>> SearchOfficer(string Input) {
        //processy stuff

        //Querying stuff
        DataAccess data = new DataAccess();
        string sql = "SELECT IdOfficer, Name FROM officers";
        List<FirstLoadOfficer> Names = await data
            .LoadData<FirstLoadOfficer, dynamic>(sql, new { }, connectionStrings.DataDB);
      
        //Sorting and Comparing stuff
        return SortedNames;        
    }
}

Ideally the target class should be backed by an abstraction (interface) and registered

//...

services.AddScoped<ISearches, Searches>();

//...

With that, it is a matter of injecting the abstraction where it is needed

@inject ISearches searches

...

@code {
    SimilarPeople = await searches.SearchOfficer("Input Name");
}

Reference ASP.NET Core Blazor dependency injection

Related