如何彻底解决IoC循环引用?
可能的重复:
依赖注入可以防止循环依赖吗?
我正在开发一个框架将有各种服务,如 dal、与共享点集成、异常处理等。
我需要在 IoC 中完成它,并且我对这种方法很陌生。[似乎有关于我正在做的事情的循环引用]
所以在我看来,我们将有三种类型的项目
- 接口:最好是一个单独的项目
- 具体类项目(如异常、dal、集成等服务项目)实现接口
- bootstrapper\configurator(配置器):最好是一个单独的项目,如果它驻留在“接口”项目中它将创建与具体类项目的循环引用,因为 IoC 需要接口和具体类的引用。
现在的事情是
具体类不应该引用任何其他具体类,因为这最终会创建循环引用。(如果存在循环引用,它是否会杀死 IoC 的整个目的,或者我错了这里?)。
其次,启动项目(单元测试、WCF服务等)应该首先加载引导程序以注册所有类型,所以我应该将引导程序项目添加到启动项目中,创建一个统一容器的实例[singleton]注册所有类型。为了解决这些类型,我需要在每个其他服务项目中使用相同的实例。
所以我必须将引导程序项目添加到服务项目中以进行类型解析。这种方法感觉不对,因为它会导致与我在第 1 点中提到的相同问题(每个服务项目都将包含服务项目的引用)。
该怎么办呢?我尝试在注册时通过属性注入将 UnityContainer 添加为每个具体类中的属性。我什至不确定这是否是正确的方法。我主要关心的是实现结果的最佳实践,因此,如果您能指导我完成此操作,我将非常感激...
提前感谢您!
还有一件事,您更喜欢哪种方式来提高性能、配置、代码内类型注册或实例注册?
如果需要,我可以上传演示项目。我可以解释一件事。 Dal 使用异常管理器,异常管理器使用转换器来获取用户友好的消息,转换器使用 DAL 来获取用户友好的消息。这是我们有循环引用的一种情况。但如果我们互相参考的话,可能会有很多。
[更新 - 包含示例代码] 我们还没有实现 IoC,所以你不会看到任何对它的引用 公共布尔更新() {
布尔结果=假;
//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;
}
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 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
与任何循环引用一样,您需要查看代码本身的实际架构。将 IoC/DI 放在一边,看看循环引用发生在哪里并进行重构。这些参考资料真的需要存在吗?您可以使用更好的设计吗?
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?
注意:我对 Unity 不太了解,但我与其他 ioc 容器一起工作过,
如果我理解正确的话,你想知道如何布局你的项目以避免循环引用。在我看来,您需要这些
(更新)示例
waqas.service. payment 需要访问 dal,而不引用 bootstrapper 或 unity:
将旧版本更改
为新版本
bootstrapper 负责创建 Dal 和 PaymentService 并将它们相互连接。 IDal 在 Waqas.Base.dll 中定义。
Note: i donot know much about
Unity
but i worked with other ioc-containersif 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)
(Update) Example
waqas.service.payment needs access to dal without referencing the bootstrapper or unity:
change form old version
to new version
The bootstrapper is responsible for creating Dal and PaymentService and connection them with each other. IDal is defined in Waqas.Base.dll.