|
|
|
|
using Connected.Annotations;
|
|
|
|
|
using Connected.Collections.Concurrent;
|
|
|
|
|
using Connected.Configuration;
|
|
|
|
|
using Connected.Entities.Caching;
|
|
|
|
|
using Connected.Hosting.Workers;
|
|
|
|
|
using Connected.Services;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
|
|
namespace Connected.Instance;
|
|
|
|
|
|
|
|
|
|
public static class StartupExtensions
|
|
|
|
|
{
|
|
|
|
|
internal static IServiceCollection AddMicroService(this IServiceCollection services, Assembly assembly)
|
|
|
|
|
{
|
|
|
|
|
foreach (var type in assembly.GetTypes())
|
|
|
|
|
{
|
|
|
|
|
if (type.IsAbstract || !type.IsClass)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
AddService(type, services, false);
|
|
|
|
|
AddArgument(type, services, false);
|
|
|
|
|
AddServiceOperation(type, services, false);
|
|
|
|
|
AddEntityCache(type, services, false);
|
|
|
|
|
AddMiddleware(type, services, false);
|
|
|
|
|
AddDispatcher(type, services, false);
|
|
|
|
|
AddDispatcherJob(type, services, false);
|
|
|
|
|
AddHostedService(type, services, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return services;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddServiceOperation(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddServiceOperation(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddServiceOperation(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (CanRegister(type, manual) && type.IsServiceOperation())
|
|
|
|
|
{
|
|
|
|
|
services.AddTransient(type);
|
|
|
|
|
RegisteredServices.AddApi(type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddService(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddService(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddService(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (type.GetInterface(typeof(IService).FullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var interfaces = type.GetInterfaces();
|
|
|
|
|
|
|
|
|
|
foreach (var i in interfaces)
|
|
|
|
|
{
|
|
|
|
|
if (i.GetCustomAttribute<ServiceAttribute>() is not null)
|
|
|
|
|
{
|
|
|
|
|
services.Add(ServiceDescriptor.Scoped(i, type));
|
|
|
|
|
RegisteredServices.AddApiService(type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddArgument(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddArgument(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddArgument(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || type.GetInterface(typeof(IDto).FullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
services.Add(ServiceDescriptor.Transient(type, type));
|
|
|
|
|
RegisteredServices.AddArgument(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddMiddleware(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddMiddleware(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
public static void AddMiddleware(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || type.GetInterface(typeof(IMiddleware).FullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var att = type.GetCustomAttribute<ServiceRegistrationAttribute>();
|
|
|
|
|
var scope = ServiceRegistrationScope.Scoped;
|
|
|
|
|
|
|
|
|
|
if (att is not null)
|
|
|
|
|
scope = att.Scope;
|
|
|
|
|
|
|
|
|
|
switch (scope)
|
|
|
|
|
{
|
|
|
|
|
case ServiceRegistrationScope.Singleton:
|
|
|
|
|
services.Add(ServiceDescriptor.Singleton(type, type));
|
|
|
|
|
break;
|
|
|
|
|
case ServiceRegistrationScope.Scoped:
|
|
|
|
|
services.Add(ServiceDescriptor.Scoped(type, type));
|
|
|
|
|
break;
|
|
|
|
|
case ServiceRegistrationScope.Transient:
|
|
|
|
|
services.Add(ServiceDescriptor.Transient(type, type));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegisteredServices.AddMiddleware(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddEntityCache(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddEntityCache(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddEntityCache(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || typeof(IEntityCacheClient<,>).FullName is not string fullName)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (type.GetInterface(fullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (var itf in type.GetInterfaces())
|
|
|
|
|
{
|
|
|
|
|
if (itf.GetInterface(fullName) is not null)
|
|
|
|
|
{
|
|
|
|
|
services.Add(ServiceDescriptor.Singleton(itf, type));
|
|
|
|
|
RegisteredServices.AddEntityCache(type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddDispatcher(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddDispatcher(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddDispatcher(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || typeof(IDispatcher<,>).FullName is not string fullName)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (type.GetInterface(fullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
services.AddTransient(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddDispatcherJob(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddDispatcherJob(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddDispatcherJob(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || typeof(IDispatcherJob<>).FullName is not string fullName)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (type.GetInterface(fullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
services.AddTransient(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void AddHostedService(Type type, IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
AddHostedService(type, services, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddHostedService(Type type, IServiceCollection services, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (!CanRegister(type, manual) || type.GetInterface(typeof(IWorker).FullName) is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
services.AddSingleton(typeof(IHostedService), type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool CanRegister(Type type, bool manual)
|
|
|
|
|
{
|
|
|
|
|
if (manual)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return type.GetCustomAttribute<ServiceRegistrationAttribute>() is not ServiceRegistrationAttribute att || att.Mode == ServiceRegistrationMode.Auto;
|
|
|
|
|
}
|
|
|
|
|
}
|