2

可能重复:
依赖注入可以防止循环依赖吗?

我正在开发一个框架,它将具有各种服务,如 dal、与共享点的集成、异常处理等。

我需要在 IoC 中做这件事,我对这种方法很陌生。[我的工作方式似乎有循环参考]

所以在我看来,我们将有三种类型的项目

  • 一个接口:最好是一个单独的项目
  • 实现接口的具体类项目(服务项目,如异常、dal、集成等)
  • 引导程序\配置(配置器):最好是一个单独的项目,如果它位于“接口”项目中,它将创建与具体类项目的循环引用,因为 IoC 需要接口和具体类的引用。

现在这就是事情

  1. 具体类不应该引用任何其他具体类,因为这最终会创建循环引用。(如果有循环引用,它不会杀死 IoC 的全部目的,还是我错了?)。

  2. 其次,启动项目(单元测试、WCF 服务等)应该首先加载引导程序以获取所有类型的注册,所以我应该将引导程序项目添加到启动项目中,创建一个统一容器的实例[单例]来注册所有类型。为了解决这些类型,我需要在每个其他服务项目中使用相同的实例。

所以我必须将引导程序项目添加到服务项目以进行类型解析。这种方法感觉不对,因为它会导致与我在第 1 点中提到的相同的问题(每个服务项目都将包含服务项目的引用)。

怎么办?我尝试在注册时通过属性注入将 UnityContainer 作为属性添加到每个具体类中。我什至不确定这是否是正确的方法。我主要关心的是实现结果的最佳实践所以如果你能指导我完成这个我将非常感激......

先感谢您!

还有一件事,您更喜欢性能、配置、代码内类型注册还是实例注册?

如果需要,我可以上传演示项目。我可以解释一件事。Dal 使用异常管理器,异常管理器使用翻译器获取用户友好消息,翻译器使用 DAL 获取用户友好消息。这是我们有循环引用的一种情况。但是如果我们互相添加引用,可能会有很多。

[更新 - 包含示例代码] 我们还没有实现 IoC,所以你不会看到任何对它的引用 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;
    }
4

2 回答 2

4

与任何循环引用一样,您需要查看代码本身的实际架构。把 IoC/DI 放在一边,看看你的循环引用发生在哪里并重构。这些参考真的需要在那里吗?有没有更好的设计可以使用?

于 2011-03-14T08:37:05.157 回答
1

注意:我不太了解,Unity但我与其他 ioc-containers 合作过

如果我对您的理解正确,您想知道如何布局您的项目以避免循环引用。在我看来,您需要这些项目(dll)

  • Waqas.Base.dll 包含所有接口。不依赖统一或任何其他 Waqas.*.dll
  • 一个或多个包含服务实现的 dll,dal,...(即 Waqas.Service.Payment.dll),仅依赖于 Waqas.Base.dll,不依赖于统一
  • 一个知道 Waqas.Base.dll 和所有其他 Waqas.*.dll 的引导程序组件(理想情况下只有一种方法)。它的唯一职责是连接系统。这是唯一知道统一性的组件。
  • 您的主应用程序和集成测试使用引导程序。
  • 如果您有单元测试,您可以通过将服务、dal 等替换为模拟来手动连接您的测试。

(更新)示例

waqas.service.payment 需要在不引用引导程序或统一的情况下访问 dal:

改变旧版本

    public class PaymentService
    {
        public PaymentService();

        SavePayment( ...)
        {
                         IDAL dal = ioCContainer.resolve<IDAL>();
                         dal.Save(...);
        }
    }

到新版本

    public class PaymentService
    {
        IDAL theDal;
        public PaymentService(IDAL dal) {theDal = dal;};

        SavePayment(...)
        {
             theDal.Save(...);
        }
    }

引导程序负责创建 Dal 和 PaymentService 并将它们相互连接。IDal 在 Waqas.Base.dll 中定义。

于 2011-03-14T08:34:13.783 回答