我有一个Autofac DI容器并使用构造函数注入将配置设置注入到我的SampleClass中。 Configuration Manager类创建为singleInstance,因此使用相同的单个实例。
public ConfigurationManager()
{
// Load the configuration settings
GetConfigurationSettings();
}
public SampleClass(IConfigurationManager configurationManager)
{
_configurationManager = configurationManager;
}
我正在配置管理器的构造函数中从App.config文件加载配置设置。我的问题是我也在验证配置设置,如果它们不在App.config文件中,则抛出异常,导致程序崩溃。这意味着我无法处理异常并返回响应。
我这样做的方式不对?是否有更好的方法来加载配置设置或者是否有办法处理抛出的异常。
修改
ConfigurationManager configurationManager = new ConfigurationManager();
configurationManager.GetConfigurationSettings();
//Try catch around for the exception thrown if config settings fail
//Register the instance above with autofac
builder.Register(configurationManager()).As<IConfigurationManager>().SingleInstance();
//Old way of registering the configurationManager
builder.Register(c => new ConfigurationManager()).As<IConfigurationManager>().SingleInstance();
答案 0 :(得分:1)
你做的绝对正确。为什么?您正在阻止在未正确配置应用程序时启动系统。你想要发生的最后一件事是系统实际启动并在以后失败。快失败!但是,请确保此异常不会丢失。您可以确保记录异常。
但有一点需要注意。一般的建议是在类型的构造函数中尽可能少地执行。只需将传入的依赖项存储在实例变量中就可以了。这种类型的构造非常快,并且永远不会真正失败。通常,构建依赖关系图应该很快,不应该失败。在您的情况下,这不会是一个问题,因为您希望系统尽快失败(在启动期间)。但是,为了遵守一般建议,您可能希望在该类型之外提取此验证过程。因此,不是在构造函数中调用GetConfigurationSettings
,而是直接从组合根(连接容器的代码)调用它,并将有效的配置设置对象提供给ConfigurationManager
的构造函数。这样你不仅可以使ConfigurationManager
变得更简单,而且可以让系统更快地失败。
答案 1 :(得分:0)
核心问题是,您通过在合成期间执行某些操作来混合对象图的组合和执行。在DI风格中,构造函数应该尽可能简单。当您的班级被要求执行一些有意义的工作时,例如调用GetConfigurationSettings
方法时,这是您认真开始的信号。
以这种方式构建事物的主要好处是它使一切更具可预测性。组合期间的错误确实是 组合错误,执行过程中的错误确实 执行错误。
工作时间也更可预测。我意识到应用程序配置在运行时并没有真正改变,但是假设你有一个读取文件的类。如果在合成期间在构造函数中读取它,则文件的内容可能会在执行期间使用该数据时发生更改。但是,如果您在执行期间读取文件,则可以保证避免使用这种形式的缓存时不可避免的时序问题。
如果缓存是算法的一部分,正如我想象的那样是GetConfigurationSettings
,那么将它作为执行的一部分而不是组合来实现它仍然是有意义的。缓存的值可能与ConfigurationManager
实例的生命周期不同。即使他们这样做,将其编码到构造函数中只留下一个选项,其中执行时缓存提供了更大的灵活性和它解决了您的异常问题。
答案 2 :(得分:-1)
我不打算在作曲时把异常作为一种好习惯。之所以如此,是因为组合可能具有相当复杂和间接的执行逻辑,使合理的异常处理几乎不可能。我怀疑你能发明什么比糟糕的更好
try
{
var someComponent = context.Resolve<SampleClass>();
}
catch
{
// Yeah, just stub all exceptions cause you have no idea of what to expect
}
我建议重新设计你的类,使得它们的构造函数不会抛出异常,除非它们确实需要这样做(例如,如果它们对于空值构造函数参数绝对无用)。然后,您将需要一些方法来初始化您的应用程序,处理错误并可能与用户进行交互以实现此目的。