gpt4 book ai didi

c# - 调用GetInstance方法后,实例的简单注入(inject)器注册

转载 作者:太空宇宙 更新时间:2023-11-03 21:05:19 25 4
gpt4 key购买 nike

我有一个方案,我有一个webAPi客户端,该客户端的构造函数中需要基本url,以及一个配置管理器类,该类从web.config中读取配置。

interface IConfigManager
{
string baseurl {get;}
}
class ConfigManager:IConfigManager
{
public string baseurl => system.configuration.ConfigruationManager.AppSettings["URL"];
}


而且我有一个调用Web API的客户端类

interface IApiClient
{
List<Products> GetProducts(string addresssufix);
}

public class ApiClient:IApiClient
{
public ApiClient(string baseUrl)
{
//----
}
List<Products> GetProducts(string addresssufix)
{
//....
}
}


所以我需要APiClient中的网址

在简单的进样器中同时注册组件。

 container.Register<IConfigManager, ConfigManager>();
var config= container.GetInstance<IConfigManager>();

container.Register<IApiClient<(()=> new ApiClient(config.baseurl));


但它说我不能在调用GetInstance后注册

最佳答案

在首次调用Register之后,Simple Injector会阻止对GetInstance的所有调用,以强制在注册和解析之间进行严格的注册。此设计可防止奇怪,难以调试和难以验证行为,如文档中更详细地here所述。

但是,就像要将注册阶段与从容器开始解析的阶段分开一样,在读取配置值时也应执行相同的操作。配置值仅应在注册阶段之前或期间在应用程序启动时加载。延迟读取配置值会导致应用程序变脆,并迫使您浏览整个应用程序以了解应用程序是否配置正确,而在启动时加载配置可以很容易地防止这种情况发生(因此,应用程序快速失败)。

这意味着,在您的情况下,使用IConfigManager抽象是没有多大意义的,因为它的唯一目的是延迟从应用程序设置中加载基本URL,但同样,应在开始时直接完成- (最好在值丢失或格式错误的情况下失败)。

考虑到这一点,我想对您的设计提出以下改进和简化:

var container = new Container();

string baseUrl = System.Configuration.ConfigruationManager.AppSettings["URL"];

if (string.IsNullOrEmpty(baseUrl))
throw new ConfigurationErrorsException("appSettings/URL is missing.");

container.RegisterSingleton<IApiClient>(new ApiClient(baseUrl));


查看如何在启动时直接读取配置并立即检查该值是否存在。之后,直接在 baseUrl构造函数中使用 ApiClient。另请注意, ApiClient已注册为 Singleton。我在这里假设 ApiClient是无状态且不可变的(这是一个好习惯)。

请注意,通过让 ApiClient依赖于 string baseUrl配置值而不是注入 IConfigManager来做正确的事情。在应用程序代码中使用 ConfigManager作为抽象通常存在问题。这种配置抽象通常会在应用程序的生存期内无限期增长,因为每次将新配置值添加到配置时,都需要更新此抽象(及其实现和可能的虚假实现)。这种抽象的使用者通常将仅依赖一个或几个配置值,而不是全部依赖。这表示 Interface Segregation Principle违反。这样做的问题是,测试该接口的使用者变得更加困难,因为您通常要确保他们使用正确的配置值。另一个问题是,从此类使用者的定义(其类型名称及其具有所需依赖项的构造函数)的定义中,无法看到实际上需要哪些配置值。

当您让使用者直接取决于他们所需的配置值时,所有这些问题都将完全解决。但同样,这甚至消除了首先需要具有此 IConfigManager抽象的需求。

请注意,尽管不允许register-resolve-register,但是您可以执行以下操作:

container.Register<IConfigManager, ConfigManager>();

container.Register<IApiClient>(() =>
new ApiClient(container.GetInstance<IConfigManager>().baseurl));


此处发生的情况是 GetInstance<IConfigManager>作为 IApiClient的委托的一部分被调用。这将起作用,因为在这种情况下,在解析 GetInstance<IConfigManager>()时(因此在注册过程之后)会调用 IApiClient。换句话说,解析 IConfigManager会延迟。

但是,有关此的重大警告:通常不建议这种做法。如前所述,当涉及到配置值时,我们不想延迟加载它们。但是即使在其他情况下,我们通常也不想这样做,因为这种构造使Simple Injector的验证和诊断系统蒙蔽了视线。由于Simple Injector使用静态可用信息(例如构造函数参数)来分析对象图,因此这种动态调用将不允许Simple Injector查找诸如 Lifestyle Mismatches之类的常见问题。换句话说,仅当您确定不会发生配置错误时,才应在极少数情况下使用此构造。

关于c# - 调用GetInstance方法后,实例的简单注入(inject)器注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41584621/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com