You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Framework/Connected.Instance/StartupExtensions.cs

195 lines
5.1 KiB

2 years ago
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;
}
}