using Medusa.Core.Services;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Collections.Generic;
using System.Reflection;
namespace Medusa.Core.Extensions
{
public static class ServiceCollectionExtensions
{
///
/// Add handler service to DI
///
/// The extended IServiceCollection
///
public static IServiceCollection AddHandlers(this IServiceCollection services)
{
services.Add(new ServiceDescriptor(typeof(IHandlerService), typeof(HandlerService), ServiceLifetime.Singleton));
services.AddTransient();
return services;
}
///
/// Adds services implementing an interface to the DI container.
///
/// The interface type
/// The extended IServiceCollection
/// The lifetime of the services
///
public static IServiceCollection AddIServicesWithType(this IServiceCollection serviceCollection,
ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var assembly = typeof(TType).Assembly;
var types = assembly.DefinedTypes
.Where(x => typeof(TType).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.ToArray();
if(types.Length == 0) return serviceCollection;
foreach(var type in types)
{
serviceCollection.TryAdd(new ServiceDescriptor(typeof(TType), type.AsType(), lifetime));
}
return serviceCollection;
}
///
/// Adds services from a namespace that implement an interface to the DI container.
///
/// The extended IServiceCollection
/// The namespace of the interfaces
/// The lifetime of the services
///
public static IServiceCollection AddServicesInNamespaceWithInterface(this IServiceCollection serviceCollection,
string interfaceNamespace, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var foundAssembly = assemblies.FirstOrDefault(x => x.DefinedTypes.Any(typeInfo => typeInfo.Namespace?.Equals(interfaceNamespace) ?? false));
if(foundAssembly == null)
{
try
{
var loaded = Assembly.Load(interfaceNamespace.Split('.')[0]);
foundAssembly = loaded;
}
catch
{
return serviceCollection;
}
}
var types = foundAssembly.DefinedTypes
.Where(x => x.Namespace == interfaceNamespace && !x.IsInterface && !x.IsAbstract && !x.ContainsGenericParameters && !x.IsNested)
.ToList();
if(types.Count == 0) return serviceCollection;
foreach(var type in types)
{
var interfaceType = type.GetInterfaces().FirstOrDefault();
if(interfaceType != null)
{
serviceCollection.TryAdd(new ServiceDescriptor(interfaceType, type.AsType(), lifetime));
}
}
return serviceCollection;
}
///
/// Adds services from multiple namespaces to the DI container.
///
/// The extended IServiceCollection
/// List of namespaces
/// The lifetime of the services
///
public static IServiceCollection AddServicesInNamespaces(this IServiceCollection serviceCollection,
string[] namespaces, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var foundAssemblies = assemblies
.Where(a => a.DefinedTypes.Any(t => namespaces.Contains(t.Namespace)))
.ToList();
var notFoundNamespaces = namespaces.Except(foundAssemblies.SelectMany(a => a.GetTypes().Select(t => t.Namespace))).ToList();
var types = new List();
foreach(var assembly in foundAssemblies)
{
var foundTypes = assembly.DefinedTypes
.Where(x => namespaces.Contains(x.Namespace) && !x.IsInterface && !x.IsAbstract && !x.IsNested)
.ToArray();
types.AddRange(foundTypes);
}
foreach(var notFound in notFoundNamespaces)
{
try
{
var assemblyName = notFound?.Split('.')[0];
var assembly = Assembly.Load(assemblyName ?? "");
var foundTypes = assembly.DefinedTypes
.Where(x => x.Namespace == notFound && !x.IsInterface && !x.IsAbstract && !x.IsNested)
.ToArray();
types.AddRange(foundTypes);
}
catch { }
}
if(types.Count == 0) return serviceCollection;
foreach(var type in types)
{
serviceCollection.TryAdd(new ServiceDescriptor(type.AsType(), type.AsType(), lifetime));
}
return serviceCollection;
}
///
/// Adds services from a single namespace to the DI container.
///
/// The extended IServiceCollection
/// The namespace to scan
/// The lifetime of the services
///
public static IServiceCollection AddServicesInNamespace(this IServiceCollection serviceCollection,
string @namespace, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var assembly = assemblies.FirstOrDefault(x => x.DefinedTypes.Any(typeInfo => typeInfo.Namespace == @namespace));
var types = assembly?.DefinedTypes
.Where(x => x.Namespace == @namespace && !x.IsInterface && !x.IsAbstract && !x.IsNested)
.ToArray();
if(types == null || types.Length == 0) return serviceCollection;
foreach(var type in types)
{
serviceCollection.TryAdd(new ServiceDescriptor(type.AsType(), type.AsType(), lifetime));
}
return serviceCollection;
}
///
/// Adds a single class as a service to the DI container.
///
/// The extended IServiceCollection
/// The class type to add
/// The lifetime of the service
///
public static IServiceCollection CreateServiceFromClass(this IServiceCollection serviceCollection,
Type serviceClassType, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
serviceCollection.TryAdd(new ServiceDescriptor(serviceClassType, serviceClassType, lifetime));
return serviceCollection;
}
///
/// Adds multiple classes as services to the DI container.
///
/// The extended IServiceCollection
/// A list of class types
/// The lifetime of the services
///
public static IServiceCollection CreateServiceFromClasses(this IServiceCollection serviceCollection,
IEnumerable serviceClassTypes, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
foreach(var serviceClassType in serviceClassTypes)
{
serviceCollection.TryAdd(new ServiceDescriptor(serviceClassType, serviceClassType, lifetime));
}
return serviceCollection;
}
///
/// Adds services based on a type that implements an interface, without adding the interface itself.
///
/// The extended interface
/// The extended IServiceCollection
/// The lifetime of the services
///
public static IServiceCollection AddServicesWithType(this IServiceCollection serviceDescriptors,
ServiceLifetime lifetime = ServiceLifetime.Transient)
{
var assembly = typeof(TType).Assembly;
var types = assembly.DefinedTypes
.Where(x => typeof(TType).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.ToArray();
if(types.Length == 0) return serviceDescriptors;
foreach(var type in types)
{
serviceDescriptors.TryAdd(new ServiceDescriptor(type.AsType(), type.AsType(), lifetime));
}
return serviceDescriptors;
}
}
}