首页 新闻 会员 周边

这样的依赖注入为什么会获取不到实例?

0
悬赏园豆:15 [已解决问题] 解决于 2020-03-07 14:07
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);
    }
}
复制代码
百香居士的主页 百香居士 | 初学一级 | 园豆:137
提问于:2020-03-06 21:18
< >
分享
最佳答案
0

试试 .NET Core 强大的泛型注入

services.AddSingleton(typeof(iCommandHandler<>), s => s.GetService(type));
收获园豆:15
dudu | 高人七级 |园豆:31003 | 2020-03-06 21:28

 Open generic service type 'Test.ICommandHandler`2[TCommand,TResponse]' requires registering an open generic implementation type. (Parameter 'descriptors')

百香居士 | 园豆:137 (初学一级) | 2020-03-06 21:36

@百香居士: 建议提供能够重现问题的示例代码。

dudu | 园豆:31003 (高人七级) | 2020-03-07 10:38

@dudu: 问题给出的就是,第一段放在任意vs单元测试的方法中,第二段在任意可以引用到的地方定义就可以了。

百香居士 | 园豆:137 (初学一级) | 2020-03-07 10:44

@百香居士: 把 services.AddSingleton(iCommandHandler, s => s.GetService(type)); 改为 services.AddSingleton(iCommandHandler, type); 就可以了。

dudu | 园豆:31003 (高人七级) | 2020-03-07 13:11

@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
{

}
百香居士 | 园豆:137 (初学一级) | 2020-03-07 13:50

@百香居士: 如果要使用 services.AddSingleton(iCommandHandler, s => s.GetService(type)); ,把 services.AddSingleton(type); 改为 services.AddSingleton(type, type); 即可。

dudu | 园豆:31003 (高人七级) | 2020-03-07 13:54

@dudu: 我找到问题所在了。我这里的type的类型是TypeInfo,一直没有发现。DI把TypeInfo识别为服务类型了...需要把services.AddSingleton(type);改成services.AddSingleton(type.AsType());

百香居士 | 园豆:137 (初学一级) | 2020-03-07 14:06

@百香居士: 赞,type.AsType() 是正解。

dudu | 园豆:31003 (高人七级) | 2020-03-07 14:12
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册