2013-08-29 3 views
0

Я новичок в инъекции зависимостей, и я пытаюсь решить проблему. У меня есть две службы. У каждой из этих служб есть методы, которые нуждаются друг в друге.Две службы зависят от eachother (исключение stackoverflow) - как решить?

Например: 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

«* Менеджер», созданный без параметров, звучит как нечто маловероятное, чтобы потребовать несколько экземпляров. что делает их одноэлементными объектами и полностью обходит проблему? – Phoshi

+0

Как насчет использования наследования имеют класс яслей, который имеет все ваши общие методы? – TheKingDave

+1

Похоже, что у вас есть неуместная ответственность. Зачем нужно, чтобы ForumManager нуждался в ссылке на SiteManager? И наоборот? – MattDavey

ответ

3

Вы не должны называть себя новыми в своих классах, которые будут тесно связаны с ними. Правильный шаблон для МОК, который позволит вам проверить каждый класс отдельно с использованием издевается является: -

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, например, a Func<ISiteManager,IForumManager>.

 ISiteManager siteManager = new SiteManager((s) => new ForumManager(s)); 

Внутри менеджер сайта, то вы можете позвонить в Func, проходя this получить IForumManager. ForumManager получает экземпляр SiteManager, а SiteManager имеет объект ForumManager.

+0

. Я использовал ваш ответ много в последние дни. Большое спасибо за очень хороший ответ! –

0

что вы делаете, и то, что вы предлагаете, вызовет исключение переполнения стека. я не знаю, почему вы хотите сделать что-то подобное, и вы не даете никаких намеков на это, но я предполагаю, что могу предложить вам создать менеджера, возможно, синглтон, возможно, только со статическим методом и делать:

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

и не держит ISiteManager в ForumManager и IForumManager в SiteManager

+0

@downvoter, пожалуйста, оставьте сообщение, чтобы я знал, что не так с ответом –

+0

Я не спустил вниз, но я думаю, что это решение представляет больше проблем, чем оно решает. Возможно, это Риз для нисходящего. – MattDavey

0

Вам явно не может иметь interdependant классы. Что вам нужно сделать, это создать отдельный класс и двигаться там методы, которые используют один и тот же время менеджер форум и 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 
} 

Таким образом, вы затормозит круговой depedency

+0

Вы * можете * иметь взаимозависимые классы. –

+0

Очевидно, что я имел в виду взаимозависимые классы, которые вызывали друг друга в конструкторах, так как был задан вопрос –

0

При использовании MVP с winforms и AutoFac у меня была такая же проблема с представлением, ссылающимся на ведущего и ведущего, ссылающегося на представление. Способ, которым я обходился, состоит в том, чтобы один из ваших классов передал себя другому, используя метод 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); 
    } 
} 

Редактировать На самом деле, вероятно, пойти с другими решениями вывешенных, Я просто смотрел на это чисто с точки зрения круговой зависимости

0

Вы должны обязательно избегать круговые зависимости. Я имею в виду, что A зависит от B и B от A.

Это как рак ваших зависимостей context. Мы использовали фреймворк Spring.net, который вопреки версии java не может включить неисправную систему, если обнаруживает такую ​​зависимость. Я должен сказать, что это приводит нас к беспорядку и часам весенних журналов, которые ищут и анализируют.

Мы определили почти 200 без каких-либо проблем, но как только мы добавили просто еще один фасоль вместе с Lazy ссылкой, он провалился. Это почти невозможно распутать наше решение, чтобы избежать этого прямо сейчас, поэтому мы зацепимся за крючок и зацепимся, пока он не сработает :-(

Смежные вопросы