Ответ 1
Да, возможно - раньше я делал что-то в этом направлении. Это мысли о том, что spring сразу ум...
В каждом решении Service Fabric есть "общедоступный" проект, содержащий только интерфейсы, которые вы хотите открыть из служб в этом приложении. Выход из этого проекта может быть упакован как пакет nuget и помещен в частный репозиторий. Вы могли бы назвать это проектом "интерфейсов", я предполагаю, но вам не нужно было бы раскрывать все интерфейсы, если бы вы хотели рассмотреть некоторые из них внутри вашего приложения; они могут быть определены в отдельном, неэкспонированном проекте.
Другие решения, которые хотят ссылаться на службы, открытые другим приложением, просто должны были вытащить соответствующий пакет nuget, чтобы получить ссылку на интерфейсы службы.
Теперь это не без проблем:
- Потребляющему приложению по-прежнему необходимо знать адреса для служб, чтобы создавать для них прокси. Вы можете либо выставить их как константы, определенные где-то в пакете nuget, либо если вы идете вниз по полному маршруту DI и не возражаете связывать себя с контейнером DI во всем мире (или фантазировать, пытаясь отвлечь его), вы можете разоблачить модуль из пакета nuget, который может регистрировать интерфейсы служб как лямбда, который создает прокси-сервер службы от имени зависимых приложений.
- Вы гораздо более уязвимы для разрыва контрактов. Вы должны быть очень осторожны в обновлении сигнатур методов, поскольку теперь вы отвечаете за гранулярность и координацию развертываний приложений/служб.
- Вы можете пойти слишком подробно - как вы заметили, инструментарий Service Fabric помогает вам иметь несколько сервисов в одном решении. Даже при таком подходе я все равно попытаюсь логически сгруппировать свои службы в какой-то степени, т.е. Не переходите на одно-однозначное сопоставление между приложением и сервисом - это определенно будет больнее, чем это стоит.
Надеюсь, что это поможет.
EDIT:
Пример регистрации сервисного интерфейса в модуле DI (стиль Autofac)...
Это будет модуль DI, который вы выставляете из открытого пакета nuget:
using System;
using Autofac;
using Microsoft.ServiceFabric.Services.Remoting.Client;
public class MyAppModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(component => ServiceProxy.Create<IMyService>(new Uri("fabric:/App/MyService"))).As<IMyService>();
// Other services...
}
}
И в Program.cs вашего приложения-потребителя вы должны включить что-то вроде этого:
public static void Main()
{
try
{
var container = ConfigureServiceContainer();
ServiceRuntime.RegisterServiceAsync(
"MyConsumingServiceType",
context => container.Resolve<MyConsumingService>(new TypedParameter(typeof(StatefulServiceContext), context))).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(MyConsumingService).Name);
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
private static IContainer ConfigureServiceContainer()
{
var containerBuilder = new ContainerBuilder();
// Other registrations...
containerBuilder.RegisterModule<MyAppModule>();
return containerBuilder.Build();
}
Конечно, этот подход будет работать, только если вы не разбиваете свои сервисы...