Подтвердить что ты не робот

Что происходит с использованием оператора, когда я перехожу к инъекции зависимостей

В настоящее время я использую следующий код:

public class MyProvider
{
    public MyProvider()
    {
    }

    public void Fetch()
    {
        using (PopClient popClient = new PopClient())
        {
            ....
        }
    }
}

Поскольку я хочу иметь возможность unit test метода Fetch и из-за того, что я не могу высмеять PopClient, я создал интерфейс и класс-оболочку, который вызывает PopClient. Мой обновленный код выглядит следующим образом:

public class MyProvider
{
    private readonly IPopClient popClient;

    public MyProvider(IPopClient popClient)
    {
        this.popClient = popClient;
    }

    public void Fetch()
    {
        using (var pop3 = popClient)
        {
            ....
        }
    }
}

Я использую Ninject для инъекции зависимостей, и я не совсем уверен, какой эффект будет иметь оператор using в обновленном коде, поскольку Ninject уже создал экземпляр PopClient и ввел его в конструктор.

Будет ли оператор using удалять объект pop3 и оставить объект popClient в отдельности, чтобы Ninject мог его обрабатывать или будет использоваться оператор using с помощью Ninject?

Каков правильный подход в этом случае? Любое понимание было бы очень полезно.

4b9b3361

Ответ 1

В переменной pop3 будет указана та же ссылка на объект IPopClient, который имеет popClient, поэтому, когда оператор using завершен, объект, на который ссылаются как локальная, так и переменная экземпляра, будет Dispose() d, возможно, помещая его в несогласованное состояние для дальнейшего использования.

Если вы хотите использовать несколько экземпляров IPopClient, по одному на вызов Fetch(), вам следует ввести "factory метод":

public class MyProvider
{
    private readonly Func<IPopClient> createPopClient;

    public MyProvider(Func<IPopClient> popClientFactory)
    {
        this.createPopClient = popClientFactory;
    }

    public void Fetch()
    {
        using (var pop3 = createPopClient())
        {
            ....
        }
    }
}

Теперь, когда вы вызываете Fetch(), он выполнит метод factory, который вернет новую ссылку на IPopClient, которая может быть использована, а затем удалена без какого-либо другого вызова этого метода.

AutoFac поддерживает внедрение методов factory для зарегистрированных типов без какой-либо дополнительной настройки (отсюда и название, я думаю); Я считаю, что при настройке контейнера Ninject вам необходимо явно зарегистрировать "getter" как метод factory для заданного типа возврата (который может быть таким же простым, как lambda ()=>new PopClient(), или он может использовать вызов разрешения контейнера метод).

Ответ 2

При настройке привязок объявите область действия:

https://github.com/ninject/ninject/wiki/Object-Scopes

Ninject вызовет dispose на объекты, которые он создал для вас, поэтому убедитесь, что вы пишете свои методы удаления в любых объектах, которые вы передаете Ninject для обработки.