In my code, I have the the following objects:
在我的代码中,我有以下对象:
- ErrorManager - controls how errors are logged in the application
- ConfigManager - controls how the configuration information is obtained
ErrorManager - 控制如何在应用程序中记录错误
ConfigManager - 控制如何获取配置信息
On the project I'm working on, the ErrorManager needs to pull configuration information using the ConfigManager instance while the ConfigManager uses the ErrorManager incase an error occurs.
在我正在进行的项目中,ErrorManager需要使用ConfigManager实例提取配置信息,而ConfigManager使用ErrorManager时会发生错误。
At the moment, I'm doing the following in code:
目前,我在代码中执行以下操作:
ErrorManager _errorManager = new CustomErrorManager();
ConfigManager _configManager = new CustomConfigManager(_errorManager);
_errorManager.SetConfigurationManager(_configManager);
Is there a way for me to clean up this circular reference of dependencies?
有没有办法让我清理这个依赖关系的循环引用?
4 个解决方案
#1
I would create the following:
我会创建以下内容:
ErrorConfig _errorConfig = ...;
// ErrorConfig is a new config object containing only ErrorManager Configuration
ErrorManager _errorManager = new CustomErrorManager(_errorConfig);
ConfigManager _configManager = new CustomConfigManager(_errorManager);
Now, the ConfigManager
can can use the ready-to-run ErrorManager without a bootstrapping problem where the ErrorManager
is not ready to handle errors.
现在,ConfigManager可以使用准备运行的ErrorManager,而不会出现BootManager未准备好处理错误的引导问题。
#2
Circular references are usually best cleaned up by refactoring a third class that both depend on. For instance, you might have something like this:
循环引用通常最好通过重构依赖的第三类来清理。例如,您可能有这样的事情:
BootstrapConfigManager _bcm = new BootstrapConfigManager();
ErrorManager _errorManager = new CustomErrorManager(_bcm);
ConfigManager _configManager = new CustomConfigManager(_bcm, _errorManager);
#3
Refactor your code. You can probably break up the classes to isolate a portion that you can initialize first and pass on to both the classes.
重构你的代码。您可以分解类以隔离可以首先初始化并传递给两个类的部分。
#4
I would create a extension methods for each called AddRelationship, passing in the other object as the parameter.
我会为每个名为AddRelationship的方法创建一个扩展方法,并将另一个对象作为参数传入。
The object passed would add the relationship and then call the AddRelationship method of the other:
传递的对象将添加关系,然后调用另一个的AddRelationship方法:
static void AddRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
this.ErrorManager = errMgr;
if (this != errMgr.ConfigManager)
errMgr.AddRelationship(this);
}
static void AddRelationship(this ErrorManager errMgr, ConfigManager configMgr)
{
this.ConfigManager = configMgr;
if (this != configManager.errMgr)
configMgr.AddRelationship(this);
}
This means that you can add the relationship using either object.
这意味着您可以使用任一对象添加关系。
ConfigManager cfg = new ConfigManager();
ErrorManager err = new ErrorManager();
//Assign using either:
err.AddRelationship(cfg);
//Or
cfg.AddRelationship(err);
You should also create RemoveRelationship extensions.
您还应该创建RemoveRelationship扩展。
static void RemoveRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
if (this.errorManager == errMgr)
{
this.errorManager = null;
if (errManager.configManager == this)
errMgr.RemoveRelationship(this);
}
}
static void RemoveRelationship(this ErrorManager errMgr, ConfigManager cfgMgr)
{
if (this.ConfigManager == cfgMgr)
{
this.configManager = null;
if (cfgMgr.errorManager == this)
cfgMgr.RemoveRelationship(this);
}
}
I don't know that circular references are a particularly good coding practice, but this should solve the question as asked.
我不知道循环引用是一种特别好的编码实践,但这应该解决问题。
#1
I would create the following:
我会创建以下内容:
ErrorConfig _errorConfig = ...;
// ErrorConfig is a new config object containing only ErrorManager Configuration
ErrorManager _errorManager = new CustomErrorManager(_errorConfig);
ConfigManager _configManager = new CustomConfigManager(_errorManager);
Now, the ConfigManager
can can use the ready-to-run ErrorManager without a bootstrapping problem where the ErrorManager
is not ready to handle errors.
现在,ConfigManager可以使用准备运行的ErrorManager,而不会出现BootManager未准备好处理错误的引导问题。
#2
Circular references are usually best cleaned up by refactoring a third class that both depend on. For instance, you might have something like this:
循环引用通常最好通过重构依赖的第三类来清理。例如,您可能有这样的事情:
BootstrapConfigManager _bcm = new BootstrapConfigManager();
ErrorManager _errorManager = new CustomErrorManager(_bcm);
ConfigManager _configManager = new CustomConfigManager(_bcm, _errorManager);
#3
Refactor your code. You can probably break up the classes to isolate a portion that you can initialize first and pass on to both the classes.
重构你的代码。您可以分解类以隔离可以首先初始化并传递给两个类的部分。
#4
I would create a extension methods for each called AddRelationship, passing in the other object as the parameter.
我会为每个名为AddRelationship的方法创建一个扩展方法,并将另一个对象作为参数传入。
The object passed would add the relationship and then call the AddRelationship method of the other:
传递的对象将添加关系,然后调用另一个的AddRelationship方法:
static void AddRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
this.ErrorManager = errMgr;
if (this != errMgr.ConfigManager)
errMgr.AddRelationship(this);
}
static void AddRelationship(this ErrorManager errMgr, ConfigManager configMgr)
{
this.ConfigManager = configMgr;
if (this != configManager.errMgr)
configMgr.AddRelationship(this);
}
This means that you can add the relationship using either object.
这意味着您可以使用任一对象添加关系。
ConfigManager cfg = new ConfigManager();
ErrorManager err = new ErrorManager();
//Assign using either:
err.AddRelationship(cfg);
//Or
cfg.AddRelationship(err);
You should also create RemoveRelationship extensions.
您还应该创建RemoveRelationship扩展。
static void RemoveRelationship(this ConfigManager configMgr, ErrorManager errMgr)
{
if (this.errorManager == errMgr)
{
this.errorManager = null;
if (errManager.configManager == this)
errMgr.RemoveRelationship(this);
}
}
static void RemoveRelationship(this ErrorManager errMgr, ConfigManager cfgMgr)
{
if (this.ConfigManager == cfgMgr)
{
this.configManager = null;
if (cfgMgr.errorManager == this)
cfgMgr.RemoveRelationship(this);
}
}
I don't know that circular references are a particularly good coding practice, but this should solve the question as asked.
我不知道循环引用是一种特别好的编码实践,但这应该解决问题。