Вызов служб WCF без использования WCF — хорошая или плохая практика?

#wcf #shared-libraries #soa #n-tier-architecture

#wcf #разделяемые библиотеки #soa #n-tier-architecture

Вопрос:

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

Концептуально это соответствует:

Клиент => Служба WCF => Библиотека служб (фактическая реализация)

или

Клиент => Библиотека служб (фактическая реализация)

в зависимости от того, где находится клиент (локальный или удаленный).

Вот простой пример:

 [ServiceContract]
public interface ICalculator
{
    [OperationContract]
    int Add(int a, int b);
}

public class Calculator : ICalculator
{
    public int Add(int a, int b)
    {
        return a   b;
    }
}

public class CalculatorFactory
{
    public static ICalculator CreateCalculator()
    {
        return new Calculator();
    }
}
  

И мое клиентское приложение выполнило следующее

 int result = CalculatorFactory.CreateCalculator().Add(1,2);
  

или

 int result = IChannelFactory<ICalculator>().CreateChannel().Add(1,2);
  

в зависимости от того, была ли она локальной или удаленной.

Является ли плохой практикой прямой вызов аннотированного кода WCF (т. Е. без использования WCF)?

Дополнительные комментарии:

  • Я понимаю, что мог бы использовать WCF во всех случаях и просто разместить службу, используя NamedPipes для локальных подключений. Я хотел бы избежать этого, если смогу, для простоты.
  • Альтернативой вышесказанному является, по существу, дублирование интерфейса ICalculator в библиотеке сервисов и изменение реализации службы WCF для включения CalculatorFactory.CreateCalculator().Add(1,2). Это кажется большими накладными расходами, учитывая, что я хочу, чтобы интерфейс был таким же.

Комментарии:

1. Не является ли второе утечкой ресурсов, потому что прокси-сервер должен быть закрыт?

2. Это не совсем относится к вопросу — выше приведен всего лишь пример кода, выдранный из моего мозга. Вопрос более концептуальный.

Ответ №1:

Вы можете создавать и использовать аннотированные классы WCF локально без каких-либо проблем, если только вы не начнете использовать некоторые функции, связанные с WCF, такие OperationContext как etc.

Обычно это абстрагируется другим способом:

Клиент => ServiceAgent => Бизнес-сервис

или

Клиент => ServiceAgent => Служба WCF => Бизнес-служба

Сам клиент не знает, является ли служба локальной или удаленной. Агент обслуживания — это компонент на стороне клиента, который на основе своей реализации либо создает локальный экземпляр службы, либо вызывает удаленную службу WCF, которая, в свою очередь, создает экземпляр бизнес-службы. ServiceAgent можно внедрить в клиент как зависимость, что сделает ваше приложение довольно хорошо настраиваемым. Также вы можете предоставить другой интерфейс в service agent (такой же, как реализован business service), и если вы хотите, чтобы служба WCF и прокси-сервер могли использовать другой.

Если вы решили использовать службу WCF постоянно, включая локальные вызовы, не используйте NamedPipes. Именованные каналы предназначены для взаимодействия между процессами на одном компьютере. Если вы хотите использовать обмен данными в том же процессе, используйте вместо этого NullTransport или Local Channel. Производительность по-прежнему хуже, чем при прямом вызове.

Комментарии:

1. 1 для локального канала — я не знал об этом. Я полагаю, что CalculatorFactory выше можно рассматривать как ServiceAgent; метод CreateCalculator может либо просто возвращать экземпляр калькулятора, либо возвращать клиентский канал. Моим главным желанием было, чтобы локальное / удаленное решение принималось разработчиком-клиентом.