Да, вы должны закрыть открытые каналы.Вы не указали, кто на самом деле использует фабрику каналов для открытия канала.Тот, кто получает открытый канал от вызова фабрики, несет ответственность за его закрытие, так как это единственное место, которое знает, когда это допустимо.
Как правило, вы должны открыть свой канал, сделатьпозвоните и немедленно закройте его, чтобы освободить соединение с пулом.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>
декораторы для применения сквозных задач, таких как безопасность на уровне сообщений - добавление заголовков и т. Д.