REST API СервисКонтракт аналог
Preambula
Я работаю над распределенной компьютерной системой, которая была написана с использованием C# и .Net Remoting в качестве технологии межпроцессного взаимодействия и в основном развернута в среде внутренней сети заказчика. Система отвечает за выполнение предварительно сконфигурированной задачи, в которой могут быть задействованы несколько физических компьютеров (один или несколько). Система была описана с помощью интерфейсов, и их использование в коде задачи было прозрачным, поэтому не имеет значения, являются ли некоторые из них объектами Proxy или локальным объектом - база кода была в одном месте. Более того, реализация этих интерфейсов была в одном месте в коде. Преимущество этого подхода в том, что когда вы как-то меняете свои интерфейсы, вы можете отразить это изменение в коде.
Основным моментом является:
Наличие контрактов на обслуживание и их реализация в единой кодовой базе 1 очень важно.
проблема
На данный момент мне нужно представить наш сервис в режиме REST и выполнить межпроцессное взаимодействие с его использованием. В соответствии с WCF и ASP.NET Web API (и, возможно, по другим причинам), был сделан выбор использовать ASP.NET Web API. Используя его, нам нужно создать класс, который наследуется от ApiController. Контроллер будет использовать контракт (интерфейс), но не будет его реализовывать.
public class ContractsController : ApiController
{
private IContracts contractsRepository;
public ContractsController(IContracts contractsRepository)
{
this.contractsRepository= contractsRepository;
}
}
Это решение было принято, потому что я не хотел бы, чтобы в контракте содержался конкретный Http, например IHttpActionResult
, HttpResponseMessage
и т. д. В то же время мой Контроллер должен быть совместим с контрактом, который он использует, поэтому вызов прокси-контракта должен быть правильно перенаправлен на правильное действие контроллера на другом конце, который вызовет тот же метод контракта. Это заставило меня написать код (на самом деле модульный тест), чтобы проверить, что контракты и контроллер синхронизированы.
Я пытался использовать некоторый генератор кода по спецификации API, такой как swagger, raml, но полученный код... вы знаете, он хорош для примера hello-world, а не для сложных приложений. Даже с использованием шаблонов - создание хорошего кода не так просто.
Если бы это был сервис WCF - все было бы здорово, потому что у нас есть [ServiceContract]
и то же самое для сервера и клиента.
пример
Вот пример, который может продемонстрировать проблему синхронизации ApiController и контракта (интерфейса), который он потребляет (операторы if здесь для простоты)
private void LongRunningAction()
{
IContract1 c1;
IContract2 c2;
if (/* contract1 belongs to local computer */)
{
c1 = container.Resolve<IContract1>();
}
else /* contract1 belongs to remote computer */
{
c1 = container.Resolve<IRemoteFactory>("RemoteComputerName").Resolve<IContract1>;
}
if (/* contract2 belongs to local computer */)
{
c2 = container.Resolve<IContract2>();
}
else /* contract2 belongs to remote computer */
{
c2 = container.Resolve<IRemoteFactory>("RemoteComputerName2").Resolve<IContract2>;
}
// Rest of the code will be the same because we operate with
// interfaces, which could be either local objects or
// proxy to the remote computer. Proxy objects will generate
// the Http request, and it will be passed to the remote ApiController,
// so the contracts and ApiControllers must be in sync.
}
Вопрос
Как обеспечить синхронизацию используемых контроллеров и контрактов ( интерфейсов)?
Какой подход использовать, чтобы избежать такой неопределенности?
1 Одна единица кода не означает один проект или одну сборку.