System.StackOverflow исключение из рекурсивной зависимости между классами - PullRequest
3 голосов
/ 05 ноября 2011

Я использую шаблон репозитория со служебным слоем в моем приложении.Чтобы следовать рекомендациям, я создаю сервис для каждого репо.

Два моих сервиса зависят друг от друга.Мне нужно вызывать по крайней мере один метод для каждого из другой службы.

Я использую внедрение зависимостей для разрешения этих зависимостей.Кажется, что проблема заключается в следующем:

  • Класс A зависит от класса B

  • Класс B зависит от класса A

мой контейнер DI разрешает все вышеперечисленное.

Я звоню в класс A, и экземпляр класса B получает инъекцию ...

Этозаставляет контейнер создавать новый экземпляр класса A для класса B ....

, который, в свою очередь, вводит новый класс A для класса B ... и так далее ...

Я думаю, что это основной недостаток дизайна с моей стороны, но я не вижу очевидного способа обойти это.

Есть идеи?

Пример

public UserService
{
    private readonly IUserRepository userRepo;
    private readonly ITransactionService transactionService;

    //ctor here....

    public ExampleUserMethod()
    {
         transactionService.GetTransactions();
         //do other things
    }

    public GetUsers()
    {
        //return users
    }


}

public TransactionService
{
    private readonly ITransactionRepository transactionRepo;
    private readonly IUserService userService;

    //ctor here....

    public ExampleTransactionMethod()
    {
         userService.GetUsers();
         //Do other things...
    }


    public GetTransactions()
    {
        //return transactions
    }

}

Ответы [ 3 ]

3 голосов
/ 05 ноября 2011

Некоторые контейнеры поддерживают циклические ссылки, если они имеют срок службы.Таким образом, A, если запрашивается, сначала создается и добавляется в кэш.Затем создается B, потому что он требуется в качестве зависимости и назначается A. Поскольку B требует, чтобы экземпляр A запрашивался, но A не создавался повторно, поскольку он найден в кеше, и этот существующий экземпляр назначен.

Но я предлагаю не использовать это решение.Лучше сначала попытайтесь разорвать круговую ссылку.Циркулярные ссылки никогда не являются хорошей идеей.Например, ваш пример:

public UserService
{
    private readonly IUserRepository userRepo;
    private readonly ITransactionStore transactionStore;

    //ctor here....

    public ExampleUserMethod()
    {
         transactionStore.GetTransactions();
         //do other things
    }

    public GetUsers()
    {
        //return users
    }


}

public TransactionService
{
    private readonly ITransactionStore transactionStore;
    private readonly IUserService userService;

    //ctor here....

    public ExampleTransactionMethod()
    {
         userService.GetUsers();
         //Do other things...
         transactionStore.AddTransaction(transaction);
    }
}

public class TransactionStore
{
    private readonly ITransactionRepository transactionRepo;

    public GetTransactions()
    {
        //return transactions
    }

    public AddTransaction()
    {
        //return transactions
    }
}
1 голос
/ 05 ноября 2011

Имея мало знаний о DI, насколько я понимаю, не имеет значения, с какой технологией вы моделируете круговую зависимость;это всегда неправильно, независимо от того, как это реализовано.

Если вы не используете DI, ваш компилятор уведомит вас;теперь, когда вы перемещаете его в среду выполнения, ошибка возникает позже, и среда выполнения уведомляет вас.

Поэтому я предлагаю удалить эту циклическую зависимость.

0 голосов
/ 05 ноября 2011

Мне кажется, что очевидный способ обойти это - переместить все вещи, которые нужны и классу А, и В, в класс С, и пусть класс А и В оба ссылаются (или получают инъекцию) на класс С

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...