tl;dr:
When I filter output of ServiceProvider.GetServices(Type)
for some reason I cannot use it later for constructing object with reflection. What am I missing?
Complete console application with DependencyInjection as its only dependency:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
namespace GenericsExperiment
{
class Program
{
static void Main(string[] args)
{
//setup DI
var services = new ServiceCollection();
services.AddTransient<ISomeHandler<Message>, MessageHandler>();
services.AddTransient<ISomeHandler<Message>, MessageHandler2>();
var serviceProvider = services.BuildServiceProvider();
//get all types of ISomeHandler<Message>
var messageType = typeof(Message);
var handlerType = typeof(ISomeHandler<>);
var handlerGenericType = handlerType.MakeGenericType(messageType);
var handlers = serviceProvider.GetServices(handlerGenericType);
//Create SomeService type and pass handlers to constructor
var someServiceType = typeof(SomeService<>);
var someServiceGenericType = someServiceType.MakeGenericType(messageType);
var concreteService = Activator.CreateInstance(someServiceGenericType,
handlers) as SomeService<Message>;
Console.WriteLine("Concrete type with all handlers created");
//same as above but this time use primitive filtering:
var filteredHandlers = serviceProvider.GetServices(handlerGenericType)
.Where(h => h.GetType().FullName.Contains("MessageHandler2")).ToList();
//this line throws exception System.MissingMethodException: Constructor on type
//'GenericsExperiment.SomeService`1[[GenericsExperiment.Message, GenericsExperiment,
//Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
var concreteServiceWithFilteredHandlers = Activator.CreateInstance(someServiceGenericType,
filteredHandlers) as SomeService<Message>;
}
}
public class Message { public string Value { get; set; } }
public interface ISomeHandler<in T> {
void Handle(T message);
}
public class MessageHandler : ISomeHandler<Message> {
public void Handle(Message message)=>Console.WriteLine($"handled: {message.Value}");
}
public class MessageHandler2 : ISomeHandler<Message> {
public void Handle(Message message) => Console.WriteLine($"handled by messageHandler 2: {message.Value}");
}
public class SomeService<T> where T : class {
public SomeService(IEnumerable<ISomeHandler<T>> handlers) { }
public void DoSomethingWithHandlers() => throw new NotImplementedException();
}
}
Aucun commentaire:
Enregistrer un commentaire