ASP.NET Core默认注入方式下如何注入多个实现(多种方式)

                    版权声明:本文为starfd原创文章,转载请标明出处。                        https://blog.csdn.net/starfd/article/details/81282651                    </div>
                                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-cd6c485e8b.css">
                                    <div id="content_views" class="markdown_views">
                <!-- flowchart 箭头图标 勿删 -->
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                                        <p>在我们开发过程中,对于服务来说,一般我们定义<code>interface</code>实现均只存在一个具体实现(有人戏称这种情况为<strong>十代单传模式</strong>),这时候Core默认的注入方式已经支持我们的需求,但对于某些抽象定义实现来讲,我们可能会有多种具体实现,在项目中,我们可能会按照具体需求选用不同的实现。</p>

首先先具体下我们的业务场景例子,假设我们有以下interface及它的两个具体实现

    public interface ILogicService
    {
        int GetNo();
    }

    public class LogicSericeImpt1 : ILogicService
    {
        public int GetNo()
        {
            return 1;
        }
    }
    public class LogicSericeImpt2 : ILogicService
    {
        public int GetNo()
        {
            return 2;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

例子非常简单,就是不同的实现返回不同的编号,下面就来讲在注入的情况下怎么获取不同的实现。

直接注入IServiceProvider的方式


因为在Core里面,IServiceProvider是允许直接注入到具体应用里的,所以就有了直接通过IServiceProvider来获取具体实现的方式。

1. 通过GetService方式

首先注入具体实现

services.AddTransient<LogicSericeImpt1>();
services.AddTransient<LogicSericeImpt2>();
  • 1
  • 2

然后在构造函数中通过如下方式获取具体实现

public TodoController(IServiceProvider serviceProvider)
{
    var s1FromProvider = serviceProvider.GetService<LogicSericeImpt1>();
    var s2FromProvider = serviceProvider.GetService<LogicSericeImpt2>();
}
  • 1
  • 2
  • 3
  • 4
  • 5

2. 通过GetServices方式

首先注入interface及具体实现

services.AddTransient<ILogicService, LogicSericeImpt1>();
services.AddTransient<ILogicService, LogicSericeImpt2>();
  • 1
  • 2

然后在构造函数中通过如下方式获取具体实现

public TodoController(IServiceProvider serviceProvider)
{
    var logicAllRegs = serviceProvider.GetServices<ILogicService>().ToList();
    var s1FromAllRegs = logicAllRegs[0];
    var s2FromAllRegs = logicAllRegs[1];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

直接注入集合的方式


这种方式其实就是省去了注入IServiceProvider的过程,直接将GetServices获取的结果进行注入。首先注入interface及具体实现

services.AddTransient<ILogicService, LogicSericeImpt1>();
services.AddTransient<ILogicService, LogicSericeImpt2>();
  • 1
  • 2

然后在构造函数中通过如下方式获取具体实现

public TodoController(IEnumerable<ILogicService> services)
{
    var s1FromServices = services.First();
    var s2FromServices = services.Skip(1).First();
}
  • 1
  • 2
  • 3
  • 4
  • 5

直接注入Func工厂的方式


在这种方式下,我们并不是直接注入具体实现,而是注入了Func这么一个工厂实现。首先我们还是需要注入具体实现

services.AddTransient<LogicSericeImpt1>();
services.AddTransient<LogicSericeImpt2>();
  • 1
  • 2

然后我们继续注入Func这个工厂,这里我们按int来返回不同的实现,当然你也可以采用其他方式比如string

services.AddSingleton(provider =>
{
    Func<int, ILogicService> func = n =>
    {
        switch (n)
        {
            case 1:
                return provider.GetService<LogicSericeImpt1>();
            case 2:
                return provider.GetService<LogicSericeImpt2>();
            default:
                throw new NotSupportedException();
        }
    };
    return func;
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

然后在构造函数中通过如下方式获取具体实现

public TodoController(Func<int, ILogicService> funcFactory)
{
    var s1FromFunc = funcFactory(1);
    var s2FromFunc = funcFactory(2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
                </div>
</article>
posted @ 2019-07-18 13:35  奋斗的中年人哈哈哈  阅读(757)  评论(0编辑  收藏  举报