how to Resolve circular reference thorough IoC? [duplicate]
Possible Duplicate:
Can dependency injection prevent a circular dependency?
I am developing a framework which will have various services like dal, integration with sharepoint, exception handling etc.
I need to do it in IoC and I am new to this approach.[there seems to be circular reference with how i am doing]
So in my opinion we will have three types of projects
- an interface: preferably a separate project
- concrete class projects(service project like exception, dal, integration etc)that implements an interface
- bootstrapper\conifiguration (configurator): preferably a separate project, if it resides in the "interface" project it will create circular reference with the concrete class projec开发者_StackOverflow社区ts as IoC requires the reference of both interface and concrete class.
now here is the thing
the concrete classes should not have reference of any other concrete class as this will end up creating circular reference.(doesn't it kill the whole purpose of IoC if there is circular reference, or am i wrong here?).
secondly the start project(unit test, WCF service etc) should load the bootstrapper first to get all the types registered, so should I add bootstrapper project to the start up project, create an instance[singleton] of the unity container to register all the types. To resolve the types I need the same instance in every other service project.
so i have to add the bootstrapper project to services projects for type resolution. This approach doesn't feel right because it will result in the same issue as i mentioned in point # 1 (every service project will contain the reference of the service projects).
How to go about it? I have tried adding the UnityContainer as a property in each concrete class through property injection at the time of registration. I am not even sure if this is the right way. My main concern is the best practice to achieve the results So if you can guide me through this i will be really thankful...
Thank you in advance!
One more thing which way you prefer for performance, configuration, in-code type Registration or instanceregistration?
If it is required i can upload the demo project. I can explain one thing. Dal uses exception manager, exception manager uses translator for user friendly message, translator uses DAL to get the user friendly message. this is one case where we have circular reference. but there can be many if we add reference in each other.
[UPDATED - sample code included] we haven't implemented IoC yet so you won't see any reference to it public bool Update() {
bool result = false; //Central DB
IDataServiceManager oDataServiceMgr = null;
DbTransaction oTrans = null;
//Client DB
IDataServiceManager oDataServiceMgrClient = null;
DbTransaction oTransClient = null;
try
{
oDataServiceMgr = new DataServiceManager(); //Connets to Centeral DB
oTrans = oDataServiceMgr.BeginTransaction();
if (this.UpdateUserData(oDataServiceMgr, oTrans)) //First Update in Center
{
oDataServiceMgrClient = new DataServiceManager(this.clientIDField); //Connects to client db
oTransClient = oDataServiceMgrClient.BeginTransaction();
if (this.UpdateUserData(oDataServiceMgrClient, oTransClient))
result = true;
}
if (result)
{
oTrans.Commit(); //Center DB
oTransClient.Commit(); //Center DB
}
}
catch (UserServiceException ex)
{
this._UserServiceException = new UserServiceException();
SnapFlow.ExceptionHandling.ExceptionHandler.Wrap(this._UserServiceException, ex, true);
throw this._UserServiceException;
}
finally
{
if (!result && oTrans != null)
oTrans.Rollback();
if (!result && oTransClient != null)
oTransClient.Rollback();
}
return result;
}
As with any circular references, you need to look at the actual architecture of the code itself. Putting IoC/DI aside, have a look at where your circular references are occurring and refactor. Do these references really need to be there? Is there a better design you can use?
Note: i donot know much about Unity
but i worked with other ioc-containers
if i understood you correctly you want to know how to layout your project in order to avoid circular reference. In my opinion you need these projects(dlls)
- Waqas.Base.dll containing all interfaces. no dependecy to unity or any other Waqas.*.dll
- one or more dlls containing implementation of services, dal, ... (i.e. Waqas.Service.Payment.dll) that only depend on Waqas.Base.dll no dependecy to unity
- One Bootstrapper component (ideally only one method) that knows Waqas.Base.dll and all other Waqas.*.dll. Its only responsibility is to wire up the system. This is the only component that knows unity.
- your main application and your integrationtest use the bootstrapper.
- if you have unittests you wire up your tests manually by replacing seriveces, dal, ... with mocks.
(Update) Example
waqas.service.payment needs access to dal without referencing the bootstrapper or unity:
change form old version
public class PaymentService
{
public PaymentService();
SavePayment( ...)
{
IDAL dal = ioCContainer.resolve<IDAL>();
dal.Save(...);
}
}
to new version
public class PaymentService
{
IDAL theDal;
public PaymentService(IDAL dal) {theDal = dal;};
SavePayment(...)
{
theDal.Save(...);
}
}
The bootstrapper is responsible for creating Dal and PaymentService and connection them with each other. IDal is defined in Waqas.Base.dll.
精彩评论