Created
December 26, 2019 13:33
-
-
Save piyoEsq/d78ec10c56d7f7c925096567a90079be to your computer and use it in GitHub Desktop.
Auto register services to DI Container of GenericHost that use Microsoft.Extensions.DependencyInjection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Reflection; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Hosting; | |
namespace Sample.GenericHost | |
{ | |
// Command | |
public interface ICommand { } | |
public interface ICommandHandler<TRequest> where TRequest : ICommand | |
{ | |
void Handle(TRequest input); | |
} | |
// Query | |
public interface IRequest { } | |
public interface IResponse<T> where T : IRequest { } | |
public interface IQueryHandler<in TRequest, out TResponse> | |
where TRequest : IRequest | |
where TResponse : IResponse<TRequest> | |
{ | |
TResponse Handle(TRequest input); | |
} | |
public interface IGetUserByIdQueryHandler : IQueryHandler<GetUserByIdRequest, GetUserByIdResponse> { } | |
// QueryHandler | |
public class GetUserByIdRequest : IRequest { } | |
public class GetUserByIdResponse : IResponse<GetUserByIdRequest> { } | |
public class GetUserByIdQueryHandler : IGetUserByIdQueryHandler | |
{ | |
public GetUserByIdResponse Handle(GetUserByIdRequest input) | |
{ | |
return null; | |
} | |
} | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
CreateHostBuilder(args).Build().Run(); | |
} | |
public static IHostBuilder CreateHostBuilder(string[] args) => | |
Host.CreateDefaultBuilder(args) | |
.ConfigureServices((hostContext, services) => | |
{ | |
services.AddHostedService<Worker>(); | |
// Register Services | |
var targetAssembly = typeof(Program).Assembly; | |
registerAllServiceOfAssembly(services, targetAssembly, targetAssembly); | |
}); | |
// Interfaceとその実装クラス全てをDI Containerへ登録 | |
static void registerAllServiceOfAssembly(IServiceCollection serviceCollection, | |
Assembly interfaceOfAssembly, | |
Assembly classofAssembly) | |
{ | |
var interfaces = interfaceOfAssembly.ExportedTypes | |
.Where(w => w.IsInterface && !w.IsGenericType) | |
.Select(_ => _); | |
var classes = classofAssembly.ExportedTypes | |
.Where(w => w.IsClass).Select(_ => _); | |
var services = from i in interfaces | |
from c in classes | |
where c.GetInterface(i.Name) != null | |
select (InterfaceType: i, ClassType: c); | |
foreach (var s in services) | |
serviceCollection.AddTransient(s.InterfaceType, s.ClassType); | |
} | |
// 指定したInterfaceの実装クラスのみDI Containerへ登録 | |
static void registerClasses(IServiceCollection serviceCollection, Assembly classOfAssembly, Type baseInterface) | |
{ | |
var classes = classOfAssembly.ExportedTypes | |
.Where(w => w.GetInterface(baseInterface.Name) != null) | |
.Select(_ => _); | |
if (!classes.Any()) | |
throw new Exception($"Not found exntended class of {baseInterface.Name} in {classOfAssembly.FullName} assembly."); | |
foreach (var c in classes) | |
serviceCollection.AddSingleton(baseInterface, c); | |
} | |
// 指定したGenericなInterfaceの実装クラスをDI Containerへ登録 | |
static void registerGenericClasses(IServiceCollection serviceCollection, Assembly classOfAssembly, Type genericType) | |
{ | |
// Predicate extended GenericClass | |
Predicate<Type> isExtendedGenericClass = p => | |
{ | |
return p.GetInterfaces().Any(a => a.IsGenericType && a.GetGenericTypeDefinition() == genericType); | |
}; | |
var interfaces = genericType.Assembly.ExportedTypes | |
.Where(w => isExtendedGenericClass(w) && w.IsInterface).Select(_ => _); | |
var classes = classOfAssembly.ExportedTypes | |
.Where(w => isExtendedGenericClass(w) && w.IsClass).Select(_ => _); | |
var services = from i in interfaces | |
from c in classes | |
where c.GetInterface(i.Name) != null | |
select (InterfaceType: i, ClassType: c); | |
if (!services.Any()) | |
throw new Exception($"Not found GenericTpye Class of {genericType.Name} in {classOfAssembly.FullName} assembly."); | |
foreach (var s in services) | |
serviceCollection.AddTransient(s.InterfaceType, s.ClassType); | |
} | |
} | |
public class Worker : BackgroundService | |
{ | |
private readonly IGetUserByIdQueryHandler _getUserByIdQuery; | |
public Worker(IGetUserByIdQueryHandler getUserByIdQuery) | |
{ | |
_getUserByIdQuery = getUserByIdQuery; | |
} | |
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |
{ | |
// Query | |
var _ = _getUserByIdQuery.Handle(new GetUserByIdRequest()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment