如何根据部署环境在静态 class 中加载 appsettings.json,以便我可以在其他 class 库中使用
How to load appsettings.json inside a Static class based on deploy environment so that I can use in other class libraries
我正在处理一个迁移项目。我需要在其他 class 库中使用我的应用程序设置。所以在谷歌搜索和 Whosebuging 之后,我将我的 appsettings.json 加载到静态 class 中,如下所示:
public static class ReadAppConfig
{
private static readonly IConfiguration Root;
private static readonly ConfigurationBuilder ConfigurationBuilder;
static ReadAppConfig()
{
if (ConfigurationBuilder == null)
{
ConfigurationBuilder = new ConfigurationBuilder();
ConfigurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
ConfigurationBuilder.AddJsonFile("appsettings.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.QA.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.Dev.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.Staging.json", optional: true);
if (Root == null)
Root = ConfigurationBuilder.Build();
}
}
public static string UserManualFile => Root.GetSection("AppSettings:SomeKey").Value;
}
所以现在我可以在其他库中像 ReadAppConfig.UserManualFile
一样获得 UserManualFile
。
这很好用。但它总是只从 appsettings.Staging.json
读取。如何根据部署环境进行阅读。
我无法在此处获取 IHostingEnvironment
,因为这是静态的 class。
请协助/建议我以正确的方式做到这一点。
谢谢
这里有两个问题。首先,不要使用静态 class。配置被设计为依赖注入,而依赖注入从根本上与静态不兼容。事实上,静态几乎总是错误的方法,依赖注入与否。其次,图书馆应该只依赖于抽象,而不是具体 data/implementations.
老实说,存在三个问题,最后一个是这里的杀手:您的用例需要 IHostingEnvironment
,并且绝对知道如何在静态 class 中获得它。游戏结束。
您可以通过多种方式前往此处,但我会坚持我认为最好的选择。最终,您的图书馆似乎只需要 UserManualFile
。因此,它们应该依赖于 all:大概是与用户手册的位置相对应的字符串。所以,你会做这样的事情:
public class SomeLibraryClass
{
private readonly string _userManualFie;
public SomeLibraryClass(string userManualFile)
{
_userManualFile = userManualFile;
}
}
这需要最少的知识,并为您的库提供最多的抽象。它不再关心它在哪里或如何获取文件位置,只关心它获取它。
然后,在您的实际应用中,您将使用强类型配置来提供此值:
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
...
services.AddScoped(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
return new SomeLibraryClass(appSettings.Value.UserManualFile);
});
完成。现在,如果图书馆确实需要其他东西,您可以选择将自定义 "settings" class 传递给图书馆。这个 class 应该来自图书馆,以便它记录它需要的东西。例如,在您的图书馆中,您可以创建一个 class,例如:
public class SomeLibrarySettings
{
public string Foo { get; set; }
public string Bar { get; set; }
// etc.
}
然后,您的图书馆 class(es) 将注入:
public SomeLibraryClass(SomeLibrarySettings settings)
最后,在您的应用中,您可以手动编写此设置 class 实例或将其注入。注入它仍然需要您手动组合它,因此只有在您要在多个 classes 之间共享它时才有意义。
手动撰写
services.AddScoped(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
var someLibrarySettings = new SomeLibrarySettings
{
Foo = appSettings.Value.Foo,
Bar = appSettings.Value.Bar,
// etc.
};
return SomeLibraryClass(someLibrarySettings);
});
注入
services.AddSingleton(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
return new SomeLibrarySettings
{
Foo = appSettings.Value.Foo,
Bar = appSettings.Value.Bar,
// etc.
};
});
services.AddScoped<SomeLibraryClass1>();
services.AddScoped<SomeLibraryClass2>();
// etc.
因为SomeLibrarySettings
注册在服务集合中,所以会自动注入到依赖它的库classes中。
最后,值得注意的是,因为您正在将配置逻辑移动到它实际所属的位置,所以您甚至不再需要担心环境问题。 ASP.NET 核心已经设置为加载适当的环境设置,因此它可以正常工作。
我正在处理一个迁移项目。我需要在其他 class 库中使用我的应用程序设置。所以在谷歌搜索和 Whosebuging 之后,我将我的 appsettings.json 加载到静态 class 中,如下所示:
public static class ReadAppConfig
{
private static readonly IConfiguration Root;
private static readonly ConfigurationBuilder ConfigurationBuilder;
static ReadAppConfig()
{
if (ConfigurationBuilder == null)
{
ConfigurationBuilder = new ConfigurationBuilder();
ConfigurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
ConfigurationBuilder.AddJsonFile("appsettings.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.QA.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.Dev.json", optional: true);
ConfigurationBuilder.AddJsonFile("appsettings.Staging.json", optional: true);
if (Root == null)
Root = ConfigurationBuilder.Build();
}
}
public static string UserManualFile => Root.GetSection("AppSettings:SomeKey").Value;
}
所以现在我可以在其他库中像 ReadAppConfig.UserManualFile
一样获得 UserManualFile
。
这很好用。但它总是只从 appsettings.Staging.json
读取。如何根据部署环境进行阅读。
我无法在此处获取 IHostingEnvironment
,因为这是静态的 class。
请协助/建议我以正确的方式做到这一点。
谢谢
这里有两个问题。首先,不要使用静态 class。配置被设计为依赖注入,而依赖注入从根本上与静态不兼容。事实上,静态几乎总是错误的方法,依赖注入与否。其次,图书馆应该只依赖于抽象,而不是具体 data/implementations.
老实说,存在三个问题,最后一个是这里的杀手:您的用例需要 IHostingEnvironment
,并且绝对知道如何在静态 class 中获得它。游戏结束。
您可以通过多种方式前往此处,但我会坚持我认为最好的选择。最终,您的图书馆似乎只需要 UserManualFile
。因此,它们应该依赖于 all:大概是与用户手册的位置相对应的字符串。所以,你会做这样的事情:
public class SomeLibraryClass
{
private readonly string _userManualFie;
public SomeLibraryClass(string userManualFile)
{
_userManualFile = userManualFile;
}
}
这需要最少的知识,并为您的库提供最多的抽象。它不再关心它在哪里或如何获取文件位置,只关心它获取它。
然后,在您的实际应用中,您将使用强类型配置来提供此值:
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
...
services.AddScoped(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
return new SomeLibraryClass(appSettings.Value.UserManualFile);
});
完成。现在,如果图书馆确实需要其他东西,您可以选择将自定义 "settings" class 传递给图书馆。这个 class 应该来自图书馆,以便它记录它需要的东西。例如,在您的图书馆中,您可以创建一个 class,例如:
public class SomeLibrarySettings
{
public string Foo { get; set; }
public string Bar { get; set; }
// etc.
}
然后,您的图书馆 class(es) 将注入:
public SomeLibraryClass(SomeLibrarySettings settings)
最后,在您的应用中,您可以手动编写此设置 class 实例或将其注入。注入它仍然需要您手动组合它,因此只有在您要在多个 classes 之间共享它时才有意义。
手动撰写
services.AddScoped(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
var someLibrarySettings = new SomeLibrarySettings
{
Foo = appSettings.Value.Foo,
Bar = appSettings.Value.Bar,
// etc.
};
return SomeLibraryClass(someLibrarySettings);
});
注入
services.AddSingleton(p =>
{
var appSettings = p.GetRequiredService<IOptions<AppSettings>>();
return new SomeLibrarySettings
{
Foo = appSettings.Value.Foo,
Bar = appSettings.Value.Bar,
// etc.
};
});
services.AddScoped<SomeLibraryClass1>();
services.AddScoped<SomeLibraryClass2>();
// etc.
因为SomeLibrarySettings
注册在服务集合中,所以会自动注入到依赖它的库classes中。
最后,值得注意的是,因为您正在将配置逻辑移动到它实际所属的位置,所以您甚至不再需要担心环境问题。 ASP.NET 核心已经设置为加载适当的环境设置,因此它可以正常工作。