Reputation: 12935
In my code, I have the the following objects:
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.
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?
Upvotes: 6
Views: 800
Reputation: 24936
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.
Upvotes: 3
Reputation: 39846
I would create a extension methods for each called AddRelationship, passing in the other object as the parameter.
The object passed would add the relationship and then call the AddRelationship method of the other:
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.
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.
Upvotes: 0
Reputation: 111200
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.
Upvotes: 0
Reputation: 5420
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);
Upvotes: 2