【问题标题】:Accessing appsettings.json (in WepApi-project) in Class library project在类库项目中访问 appsettings.json(在 Web Api 项目中)
【发布时间】:2018-11-06 12:16:30
【问题描述】:

我知道这个问题之前已经得到回应,但我似乎无法让它在我的情况下工作。 Visual Studio 中的解决方案包含多个项目,包括 WepApi-project (asp.net core) 和一个类库项目。在类库项目中,我需要访问位于 WebApi 项目中的 appsettings.json 中的一些信息。我尝试按照不同的教程进行操作,到目前为止,结果如下:

Appsettings.json

{
   "LoginSettings": {
   "email": "test@test.com",
   "password": "12345678"
   } 
}

类建模配置(驻留在类库项目中):

登录设置

public class LoginSettings
{
    public string Email { get; set; }
    public string Password { get; set; }
}

Startup.cs(WebApi 项目):

public void ConfigureServices(IServiceCollection services)
{

     var loginSettings = new LoginSettings
     {
         Email = Configuration["LoginSettings:email"],
         Password = Configuration["LoginSettings:password"]
     };

     services.AddSingleton(loginSettings);
     services.AddOptions();
}

我需要设置的类

public static class Test
{
   private readonly LoginSettings settings;

   public static async Task<string> GetTokenAsync()
   {
       var email = settings.Email;

       ...
   }

}

我无法从 LoginSettings 获得任何信息。此外,为了将 LoginSettings 注入构造函数,我尝试使 Test-class 非静态。但是当我尝试实例化 Test-class 时,它会要求一个 LoginSettings 实例。我真的不觉得让 Test-class 非静态,因为它的唯一目的是将字符串返回到另一个类,并且它需要 LoginSettings 这样做。我做错了什么?

问候。

编辑

我已将类 Test 设为非静态。实例化时我要传入什么?

【问题讨论】:

  • 如果您的测试类是非静态的,您应该能够执行以下操作:拥有一个私有类级变量(就像您一样,但稍微改变名称)private readonly LoginSettings _settings;,并注入通过您的构造函数进行类,如下所示:public Test(LoginSettings settings) { _settings = settings; }。您现在应该可以在 Test 类中使用 _settings。
  • 但是当我实例化Test-class时,我仍然需要注入一个LoginSetting?
  • 好吧,因为你用这行services.AddSingleton(loginSettings); 注入了 LoginSettings,它应该可以在应用程序范围内访问。你应该仍然可以这样做:var email = _settings.Email; 然后使用Test.GetTokenAsync(); 而不必实例化测试。试试看它是否有效,我只是在这一点上吐个球。
  • @ChristopherLake,我通过将 LoginSettings 注入到 Test-class 中,并将 Test-class 注入到使用它的类中来使其工作。我想我还需要大量的学习才能掌握这一切。不过谢谢你的帮助。
  • 我们中的任何人都不会停止学习这个职业——如果你问我,这就是福利之一。很高兴我能提供一些帮助:)

标签: asp.net asp.net-core


【解决方案1】:

Startup.cs

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

在控制器中:

public class HomeController : Controller
{
    private string _email { get; set; }
    private string _password { get; set; }

    public HomeController(IOptions<LoginSettings> options)
    {
        var login = options.Value;
        _email = login.Email;
        _password = login.Password;
    }

    public IActionResult GetTokenAsync()
    {
        // _email: "test@test.com"
        // _password: "12345678"
    }
}

注意:我建议您将appsettings.json中的属性名称命名为:

{
   "LoginSettings": {
       "Email": "test@test.com",
       "Password": "12345678"
   } 
}

使用EmailPassword 代替emailpassword

更新(针对I'm not going to use the LoginSettings in a controller. I'm going to use it in a class in the class library project):

public class MyLib
{
    private string _email { get; set; }
    private string _password { get; set; }

    public MyLib(IOptions<LoginSettings> options)
    {
        var login = options.Value;
        _email = login.Email;
        _password = login.Password;
    }

    public async Task<string> GetTokenAsync()
    {
        // _email: "test@test.com"
        // _password: "12345678"
    }
}

更新 2

使用这个库。你不能这样使用它:

var lib = new MyLib(???)

由于MyLib(或您的示例中的Test)是一项服务,因此您在使用之前将其传递给另一个构造函数:

public class AnotherClass
{
    private MyLib _lib { get; set; }

    public AnotherClass(MyLib lib)
    {
        _lib = lib;
    }

    public async Task UseIt()
    {
        var token = await _lib.GetTokenAsync();
    }
}

【讨论】:

  • 我不会在控制器中使用 LoginSettings。我打算在类库项目的一个类中使用它。
  • @Frederik 是一样的。检查我的答案中的更新。
  • 可以将类用作静态类吗?所以我会调用类似 Test.GetTokenAsync 的东西?然后 GetTokenAsync 将在方法内部负责从 appsettings 获取值。还是我完全错了?
  • 两个答案都有一个相同的想法:注册一个新服务并通过构造函数传递它。因为你需要一个静态类。它不应该工作。您不能使用静态类调用服务。
  • 好吧,我现在已经修改成非静态了。但是,当我尝试实例化(以 MyLib 为例)时,它要求输入参数 IOptions,例如:var lib = new MyLib(???)。我要传递什么?
【解决方案2】:

好的,我正在尝试解释它在我的情况下是如何工作的。

在我的 ClassLibrary 我有以下扩展方法

public static class MyClassLibraryExtensions
{
    public static IServiceCollection AddMyClassLibrary(this IServiceCollection services, LoginSettings options)
    {
        services.AddSingleton<LoginSettings>(options);
        return services;
    }
}

然后在 Web.API 项目中

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();

    var loginSettings = new LoginSettings
    {
        Email = Configuration["LoginSettings:email"],
        Password = Configuration["LoginSettings:password"]
    };

    services.AddMyClassLibrary(loginSettings);
    ...
}

并使用它

public class Test
{
   private readonly LoginSettings _settings;

   public Test(LoginSettings loginSettings)
   {
        _settings = loginSettings;
   }

   public static async Task<string> GetTokenAsync()
   {
       var email = _settings.Email;

       ...
   }
}

【讨论】:

  • 不能在静态类中声明实例成员。
  • 哦,是的。你需要静态类吗?
  • @CodeCaster 好的,谢谢,已修复。还有... 是什么使代码不起作用。它只是举例,我认为不值得被否决。所以它绝对不能编译,因为... 也作为问题的代码
  • @RomanMarusyk,我添加了... 来模拟更多预期的代码(虽然不在示例中)。
  • @Frederik 是的,我知道,没关系。这是 CodeCaster 评论的答案
猜你喜欢
  • 1970-01-01
  • 2020-09-04
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多