how to Resolve circular reference thorough IoC?

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
  • bootstrapperconifiguration (configurator): preferably a separate project, if it resides in the "interface" project it will create circular reference with the concrete class projects 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, ... (ie 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.

    链接地址: http://www.djcxy.com/p/96602.html

    上一篇: CommonceS适用于Appcelerator Titanium中的OOP

    下一篇: 如何通过IoC解决循环引用?