我是依赖注入的新手,我正试图解决一个问题。我有两项服务。这些服务中的每一种都有相互需要的方法。
例如:SiteManager
有方法需要我的ForumManager
。我的ForumManager
方法需要SiteManager
。
我有以下两个类:
public class SiteManager:ISiteManager
{
public IForumManager ForumManager { get; set; }
public SiteManager()
{
this.ForumManager = new ForumManager();
}
}
public class ForumManager:IForumManager
{
public ISiteManager SiteManager { get; set; }
public ForumManager()
{
this.SiteManager = new SiteManager();
}
}
很明显,这会导致堆栈溢出异常,因为它们会互相调用。我在这里看过很多帖子,我想我只需要一些关于如何解决这个问题的小提示。我在他们自己的程序集中有我的接口。
我考虑过将依赖项放在自己的属性中,所以当它们被使用时,它们就会被创建出来。但是,这是最佳做法吗?
我不使用IoC容器(之前我没有使用过它)。
有关如何以“最佳实践”方式解决此特定问题的任何提示! : - )
答案 0 :(得分:3)
你不应该在你的课程中调用新课程,这样会紧紧联系起来。允许您使用模拟单独测试每个类的IOC的正确模式是: -
public class SiteManager:ISiteManager
{
private readonly IForumManager forumManager;
public SiteManager(IForumManager forumManager)
{
this.forumManager = forumManager;
}
}
public class ForumManager:IForumManager
{
private readonly ISiteManager siteManager;
public ForumManager(ISiteManager siteManager)
{
this.siteManager = siteManager;
}
}
但是,这并不能解决相互递归问题。解决这个问题的最简单方法是不对其中一个类使用构造函数注入,而是使用属性注入,即将SiteManager返回到ForumManager上的公共属性,并在创建两个对象后设置它。
您的设置代码会: -
IForumManager forumManager = new ForumManager();
ISiteManager siteManager = new SiteManager(forumManager);
forumManager.SiteManager = siteManager;
另一种方法是将ForumManagerFactory传递给SiteManager,例如: Func<ISiteManager,IForumManager>
。
ISiteManager siteManager = new SiteManager((s) => new ForumManager(s));
在站点管理器中,您可以调用Func,传递this
以获取IForumManager。 ForumManager获取SiteManager的实例,SiteManager具有ForumManager对象。
答案 1 :(得分:0)
您正在做什么以及您建议的两者都会导致堆栈溢出异常。我不知道你为什么要做那样的事情而且你没有提供任何暗示,但我想我可以为你创建一个经理,也许是一个单身人士,也许只是用静态方法做:
public static void DoStuff(ISiteManager sm, IForumManager fm)
{
// your code here can use the best of both without SO
}
并且未在ISiteManager
和ForumManager
中IForumManager
中持有SiteManager
答案 2 :(得分:0)
你显然不能有相互依赖的课程。你需要做的是创建一个单独的类并移动那些使用同一时间论坛管理器和sitemanger的方法:这是一个示例第三类:
class ForumAndSiteManager
{
public ForumAndSiteManager(ISiteManager siteMaanger, IForumManager forumManager)
{
//save the injected object to private fileds
}
//define methods which will use both sitemanager and forum manager
}
这样你就会制止循环依赖
答案 3 :(得分:0)
当使用带有winforms和AutoFac的MVP时,我在引用演示者和引用视图的演示者的视图中遇到了同样的问题。我绕过它的方法是让你的一个类使用Initialize方法将自己传递给另一个。我不确定这是否是最佳做法,但我之前已经看过它(this question about mvp)
因此,对于实施细节:
public class SiteManager:ISiteManager
{
public IForumManager ForumManager { get; set; }
public SiteManager()
{
}
public Initialize(IForumManager forumManager)
{
ForumManager = forumManager
}
}
public class ForumManager:IForumManager
{
public ISiteManager SiteManager { get; set; }
public ForumManager(ISiteManager siteManager)
{
this.SiteManager = new SiteManager();
this.SiteManager.Initialize(this);
}
}
编辑实际上可能会与发布的其他解决方案一起使用,我只是从循环依赖的角度来看这个
答案 4 :(得分:0)
你绝对应该避免循环依赖。我的意思是A取决于A上的B和B.
这就像你的context
依赖的癌症。我们使用了spring.net框架,如果它发现这种依赖,那么与java版本相反,它无法打开失败的系统。我不得不说,这只会给我们带来麻烦和数小时的春天日志搜索和分析。
我们定义了近200个没有任何问题,但是一旦我们添加只是另一个bean 以及Lazy
引用它失败了。现在几乎不可能解开我们的解决方案来避免它,所以我们在它失败的时候钩住钩子和钩子: - (