0

我是依赖注入的新手,我正在尝试解决一个问题。我有两个服务。这些服务中的每一个都有需要彼此的方法。

例如:SiteManager在需要 my 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 容器(而且我以前没有使用过)。

有关如何以“最佳实践”方式解决此特定问题的任何提示!:-)

4

5 回答 5

3

你不应该在你的类中调用 new,这会使它们紧密耦合。允许您使用模拟分别测试每个类的 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 对象。

于 2013-08-29T08:23:58.963 回答
0

你在做什么和你所建议的两者都会导致堆栈溢出异常。我不知道你为什么要做这样的事情并且你没有给出任何提示,但我想我可以让你创建一个经理,也许是一个单身人士,也许只是使用静态方法并执行:

public static void DoStuff(ISiteManager sm, IForumManager fm)
{
  // your code here can use the best of both without SO
}

而不是坚持ISiteManager和坚持ForumManagerIForumManagerSiteManager

于 2013-08-29T08:05:47.990 回答
0

你显然不能有相互依赖的类。您需要做的是创建一个单独的类并将使用相同时间论坛管理器和站点管理器的方法移到那里:这是一个示例 3rd 类:

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
}

这样,您将停止循环依赖

于 2013-08-29T08:09:10.900 回答
0

在将 MVP 与 winforms 和 AutoFac 一起使用时,我遇到了与引用演示者的视图和引用视图的演示者完全相同的问题。我解决它的方法是让你的一个类使用 Initialize 方法将自己传递给另一个类。我不确定这是否是最佳实践,但我之前已经看到过它的建议(这个关于 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);
    }
}

编辑实际上可能会与发布的其他解决方案一起使用,我只是从循环依赖的角度来看这个

于 2013-08-29T08:13:40.027 回答
0

你绝对应该避免循环依赖。我的意思是A取决于B,B取决于A。

这就像你context依赖的癌症。我们使用了 spring.net 框架,它与 java 的版本相反,如果发现这种依赖关系,则无法打开失败的系统。我不得不说,这只会给我们带来混乱和数小时的 spring 日志搜索和分析。

我们定义了将近 200 个没有任何问题,但是一旦我们添加了另一个 beanLazy引用,它就失败了。现在几乎不可能解开我们的解决方案来避免它,所以我们在它失败时钩住和钩住:-(

于 2013-08-29T13:55:22.307 回答