C# 在ConfigureServices-AddScoped期间使用注入的类实现选项模式

C# 在ConfigureServices-AddScoped期间使用注入的类实现选项模式,c#,.net,design-patterns,dependency-injection,C#,.net,Design Patterns,Dependency Injection,我有一个小班,在我的几个MVC应用程序上获取关于我的用户的一系列信息。一个最小的可复制示例是: 公共类信息获取程序 { 公共字符串GetUserInformation(字符串连接str、字符串存储过程名称、int userId) { //SQL工作吗 退货信息; } } 我在ConfigureServices步骤中使用 services.AddScoped 然后在我的课堂上,我简单地从DI中调用它 现在,显然connectionStr和storedProcedure只在每个应用程序中更改,但

我有一个小班,在我的几个MVC应用程序上获取关于我的用户的一系列信息。一个最小的可复制示例是:

公共类信息获取程序
{
公共字符串GetUserInformation(字符串连接str、字符串存储过程名称、int userId)
{
//SQL工作吗
退货信息;
}
}
我在ConfigureServices步骤中使用

services.AddScoped
然后在我的课堂上,我简单地从DI中调用它

现在,显然connectionStr和storedProcedure只在每个应用程序中更改,但现在我将其作为参数传递

我尝试将这些参数公开,并使用服务进行配置。配置,但当我从控制器调用它时,会得到空值

services.AddOptions();
配置(选项=>
{
options.ConnectionString=Configuration.GetSection(“Model”).GetSection(“ConnectionString”).Value;
options.StoredProcedureName=“prInformationGetter”;
});
我不确定这失败的原因是因为我在我的原始类中缺少一个接口,还是我没有理解这个概念

我还考虑过做一些类似于
services.AddInformationGetter(options=>{})
的事情,但我的理解是,这种模式是为了实现中间件,而不是专门用于DI


我试图查看文档(docs.microsoft.com),但我更加困惑。

可能对涉及的概念有误解

Configure
将注册
IOptions
。在您的示例中,现在有两个独立的注册

当你注册课程的时候

services.AddScoped<InformationGetter>()
InformationGetter
看起来像一个服务

我建议重构遵循更单一的责任原则(SRP)和关注点分离(Soc)设计

我将完全避免选项模式,只使用委托工厂注册类,从配置中提取我需要的内容。这样,您的代码就不会与诸如
IOptions

public void ConfigureServices(IServiceCollection services) {

    //...

    InformationGetterOptions options = new InformationGetterOptions {
        ConnectionString = Configuration.GetSection("Model").GetSection("ConnectionString").Value;
        StoredProcedureName = "prInformationGetter";
    };
    services.AddSingleton(options);
    services.AddScoped<IInformationGetter, InformationGetter>();

    //...
}
public void配置服务(IServiceCollection服务){
//...
InformationGetterOptions选项=新的InformationGetterOptions{
ConnectionString=Configuration.GetSection(“Model”).GetSection(“ConnectionString”).Value;
StoredProcedureName=“prInformationGetter”;
};
服务。AddSingleton(选项);
services.addScope();
//...
}

现在,
IInformationGetter
可以在需要的地方注入,并具有执行其功能所需的所有依赖项。

因此,如果Configure已经注册了该类,我还需要执行AddScoped吗?或者不需要执行AddScoped吗?Configure注册一个封装该类的IOptions。我会完全避免选项,只是使用委托工厂注册类,从配置中提取我需要的内容。您是否也可以使用您的建议进行更新?我正在学习,所以看到所有选项之间的差异将帮助我更好地理解我在做什么。@narsher check update。任何额外的事情都必须在一个新问题中完成,因为它将偏离问题的原始范围。非常感谢您的更新和建议。这让我的学习之旅变得更好:)
public class InformationGetter {
    public string ConnectionString { get; set; }
    public string StoredProcedureName { get; set; }
    //...

    public string GetUserInformation(int userId) {
        // Do SQL work
        return info;
    }
}
//Needed by InformationGetter to perform its function
public class InformationGetterOptions {
    public string ConnectionString { get; set; }
    public string StoredProcedureName { get; set; }
}

//abstraction of InformationGetter
public interface IInformationGetter {
    string GetUserInformation(int userId);
}

//implementation.
public class InformationGetter : IInformationGetter{  
    private readonly InformationGetterOptions options;

    public InformationGetter(InformationGetterOptions options) {
        this.options = options;
    }

    public string GetUserInformation(int userId) {

        //use values in options to connect

        // Do SQL work
        return info;
    }
}
public void ConfigureServices(IServiceCollection services) {

    //...

    InformationGetterOptions options = new InformationGetterOptions {
        ConnectionString = Configuration.GetSection("Model").GetSection("ConnectionString").Value;
        StoredProcedureName = "prInformationGetter";
    };
    services.AddSingleton(options);
    services.AddScoped<IInformationGetter, InformationGetter>();

    //...
}