var services = new ServiceCollection(); foreach (var type in GetType().Assembly.DefinedTypes) { var interfaces = type.GetInterfaces() .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>)) .ToArray(); if (!interfaces.Any()) continue; services.AddSingleton(type); foreach (var iCommandHandler in interfaces) { Assert.AreEqual(typeof(ICommandHandler<Command1, int>), iCommandHandler); services.AddSingleton(iCommandHandler, s => s.GetService(type)); } } Assert.IsTrue(services.Any(d => d.ServiceType == typeof(ICommandHandler<Command1, int>))); var serviceProvider = services.BuildServiceProvider(); var ex = Assert.ThrowsException<InvalidOperationException>(() => { // var command1Handler = serviceProvider.GetRequiredService(typeof(ICommandHandler<Command1, int>)); // error too! var command1Handler = serviceProvider.GetRequiredService<ICommandHandler<Command1, int>>(); }); Assert.AreEqual( "No service for type 'Test.ICommandHandler`2[Test.Command1,System.Int32]' has been registered.", ex.Message); // Assert.AreEqual(1, command1Handler.Handle(new Command1()));
public interface ICommand<TResponse> { } public interface ICommandHandler<in TCommand, TResponse> where TCommand : ICommand<TResponse> { Task<TResponse> Handle(TCommand request); } public class Command1 : ICommand<int> { } public class CommandsHandler : ICommandHandler<Command1, int> { public Task<int> Handle(Command1 request) { Console.WriteLine("Command1 has been handled"); return Task.FromResult(1); } }
试试 .NET Core 强大的泛型注入
services.AddSingleton(typeof(iCommandHandler<>), s => s.GetService(type));
Open generic service type 'Test.ICommandHandler`2[TCommand,TResponse]' requires registering an open generic implementation type. (Parameter 'descriptors')
@百香居士: 建议提供能够重现问题的示例代码。
@dudu: 问题给出的就是,第一段放在任意vs单元测试的方法中,第二段在任意可以引用到的地方定义就可以了。
@百香居士: 把 services.AddSingleton(iCommandHandler, s => s.GetService(type));
改为 services.AddSingleton(iCommandHandler, type);
就可以了。
@dudu: 这样确实可以,但不符合我的需求。我的想法是,如果一个类实现多个服务(接口),那么这个类只需要构造一次去执行多个服务。而如果直接用类型去分别注入依赖的话,请求不同的接口就会有不同的实例被构造了。详细看下面代码:
[TestMethod] public void TestMicrosoftDI() { var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton<I1, Test>(); serviceCollection.AddSingleton<I2, Test>(); var services = serviceCollection.BuildServiceProvider(); Assert.AreNotEqual(services.GetRequiredService<I1>().GetHashCode(), services.GetRequiredService<I2>().GetHashCode()); } [TestMethod] public void TestMicrosoftDITryAdd() { var serviceCollection = new ServiceCollection(); serviceCollection.TryAddSingleton<I1, Test>(); serviceCollection.TryAddSingleton<I2, Test>(); var services = serviceCollection.BuildServiceProvider(); Assert.AreNotEqual(services.GetRequiredService<I1>().GetHashCode(), services.GetRequiredService<I2>().GetHashCode()); }
public interface I1 { } public interface I2 { } public class Test : I1, I2 { }
@百香居士: 如果要使用 services.AddSingleton(iCommandHandler, s => s.GetService(type));
,把 services.AddSingleton(type);
改为 services.AddSingleton(type, type);
即可。
@dudu: 我找到问题所在了。我这里的type的类型是TypeInfo,一直没有发现。DI把TypeInfo识别为服务类型了...需要把services.AddSingleton(type);改成services.AddSingleton(type.AsType());
@百香居士: 赞,type.AsType()
是正解。