WCF и внедрение зависимостей - PullRequest
2 голосов
/ 13 января 2012

У меня есть набор служб WCF, реализованных с использованием внедрения зависимостей в целях тестирования.

По сути, эти сервисы иногда вызывают друг друга, поэтому в своих модульных тестах я мог имитировать как репозитории, так и сервисы WCF, просто используя интерфейсы и вставляя их как компоненты в конструкторы сервисов.

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

Я также реализовал свои собственные прокси-серверы, чтобы избежать использования ссылки на службу Visual Studio (которая создает много мусора), поэтому я использую метод ChannelFactory CreateChannel.

Я немного беспокоюсь о том, что происходит в живом окружении.

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

Это создаст проблемы? Будет ли сборщик мусора позаботиться об этом? Соединения останутся открытыми? Это неправильный подход?

Большое спасибо.

Ответы [ 2 ]

2 голосов
/ 13 января 2012

ChannelFactory создает объект канала при вызове метода CreateChannel.Этот объект канала является тем, что на самом деле имеет соединение.

Как только вы закончите работу с каналом, вы должны закрыть его, вызвав для него метод IClientChannel.Close.Это должно привести к закрытию любого основного сетевого подключения.Обратите внимание, что в некоторых ситуациях вызов метода Close может вызвать исключение CommunicationObjectFaptedException, даже если вы сначала проверите, что ваш канал не находится в состоянии Faulted.

Вы можете увидеть в примере кода этогоСтраница документации MSDN о том, что метод Close вызывается для объекта wcfClientChannel.

0 голосов
/ 18 августа 2012

Да, вы должны закрыть открытые каналы.Вы не указали, кто на самом деле использует фабрику каналов для открытия канала.Тот, кто получает открытый канал от вызова фабрики, несет ответственность за его закрытие, так как это единственное место, которое знает, когда это допустимо.

Как правило, вы должны открыть свой канал, сделатьпозвоните и немедленно закройте его, чтобы освободить соединение с пулом.ChannelFactory<T> оптимизирован для этого и будет повторно использовать доступные соединения, когда это будет практично, и только контракты будут обработаны и т. Д., Один раз.

Учитывая эти моменты, мой фаворит пока имеет другую абстракцию для явного определения этих открытых.вызвать-закрыть семантику.Я называю это IChannelInvoker<T>, у которого есть единственный Execute метод.Сейчас у меня есть только асинхронная версия, но для простоты вот как будет выглядеть синхронная версия:

public interface IChannelInvoker<TChannel>
{
    /// <summary>
    /// Executes a method within the context of an open channel
    /// </summary>
    TResult Execute<TResult>(Func<TChannel, TResult> method);
}

Метод реализации Execute использует ChannelFactory для открытия канала, вызываетделегат закрывает канал и возвращает результат.У меня есть фабрика, введенная туда, и хранящаяся в течение всего срока службы приложения.

Теперь в службе A вместо введения канала T вы вводите IChannelInvoker<T>.Например:

public class ServiceA : IServiceA
{
    private readonly IChannelInvoker<IServiceB> _b;

    public ServiceA(IChannelInvoker<IServiceB> b)
    {
        _b = b;
    }

    public void SomeOperationA()
    {
        _b.Execute(channel => channel.SomeOperationB());
    }
}

Вызывающий также является составным, так что вы можете добавить другие IChannelInvoker<T> декораторы для применения сквозных задач, таких как безопасность на уровне сообщений - добавление заголовков и т. Д.

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