在.NET Core中处理一个接口多个不同实现的依赖注入问题

在.NET Core中处理一个接口多个不同实现的依赖注入问题,第1张

概述前言近段时间在准备公司的技术分享,所以这段时间将大部分时间放在准备分享内容上去了。博客也就停了一下下。在.NET Core中处理依赖注入问题时,往往是定义好了一个 *** 作规范的接口,会有N多个基于不同技术的实现,根据实际情况在项目中去使用某一个实现。但是偶尔会出现这样的情况,在某一个地方,需要同时使用到两种或两种以上的实现,这个时候我们要怎么处理呢?借助Autofac等第三方组件时,是可以很容易的实现,但是在写一些基础类库时会避免直接引用太多依赖组件。所以这里是只用微软自带的DI(Microsoft.Extensions.DependencyInjection)去处理。例子引入现在有一个接口和两个实现类。public interface IDemoService{string Get();}public class DemoServiceA : IDemoService{public string Get(){return "Service A";}}public class DemoServiceB : IDemoService{public string Get(){return "Service B";}}常规的方法,我们先在Startup中的ConfigureServices方法中添加我们的service。public void ConfigureServices(IServiceCollection services){services.AddSingleton<IDemoService, DemoServiceA>();services.AddSingleton<IDemoService, DemoServiceB>();services.AddMvc();}然后在控制器中使用private IDemoService _serviceA;private IDemoService _serviceB;public ValuesController(IDemoService serviceA, IDemoService serviceB){_serviceA = serviceA;_serviceB = serviceB;}// GET api/values[HttpGet]public string Get(){return $"{_serviceA.Get()}-{_serviceB.Get()}";}我们的预期结果是:Service A-Service B,可是上面代码的实际结果却并不像我们想的那么简单!!可以看到这里输出的都是Service B,连Service A的影子都没有看到。其实,从代码都可以看出来,它只能拿到其中一个Service的实现类!那么我们要息怎样处理才能达到我们想要的效果呢?其实思路比较简单,上面导致不能拿到对应实现类,本质上来讲应该说是它区分不了那个才是想要的!我们想个办法让它能区分就好了。处理方法给我们的Service起个别名!先是Startup中的ConfigureServices方法。public void ConfigureServices(IServiceCollection services){services.AddSingleton<DemoServiceA>();services.AddSingleton<DemoServiceB>();services.AddSingleton(factory =>{Func<string, IDemoService> accesor = key =>{if (key.Equals("ServiceA")){return factory.GetService<DemoServiceA>();}else if (key.Equals("ServiceB")){return factory.GetService<DemoServiceB>();}else{throw new ArgumentException($"Not Support key : {key}");}};return accesor;});services.AddMvc();}这里并没有直接向上面那样一次性指定接口和对应的实现类,而是用了AddSingleton的另一个重载方法。先将实现类注册一下然后再注册一下Func<string, IDemoService>先来说说这个Func<string, IDemoService>里面的string和IDemoService都分别代表什么。string 毫无疑问就是我们上面说到的别名IDemoService 这个就是我们要用的Service核心在于,factory参数是IServiceProvider类型的!所以我们可以根据这个factory去找到我们前面注册的实现类。这样解释一下,是不是就清晰了呢?然后再来看看在控制器上面怎么用。private IDemoService _serviceA;private IDemoService _serviceB;private readonly Func<string, IDemoService> _serviceAccessor;public ValuesController(Func<string, IDemoService> serviceAccessor){this._serviceAccessor = serviceAccessor;_serviceA = _serviceAccessor("ServiceA");_serviceB = _serviceAccessor("ServiceB");}// GET api/values[HttpGet]public string Get(){return $"{_serviceA.Get()}-{_serviceB.Get()}";}最后看看结果是不是和我们的预期一样。结果与预期一致。总结一对一,或许是最好的方法,也是最为理想的,这样能避开很多不必要的问题。但是现实中总会出现特殊情况,面对这些特殊情况,我们也是需要能够重容的面对。如果您有更好的处理方法,也可以留言讨论。文中的示例代码 DIDemo

<h2 ID="前言">前言

近段时间在准备公司的技术分享,所以这段时间将大部分时间放在准备分享内容上去了。博客也就停了一下下。

在.NET Core中处理依赖注入问题时,往往是定义好了一个 *** 作规范的接口,会有N多个基于不同技术的实现,根据实际情况在项目中去使用某一个实现。

但是偶尔会出现这样的情况,在某一个地方,需要同时使用到两种或两种以上的实现,这个时候我们要怎么处理呢?

借助autofac等第三方组件时,是可以很容易的实现,但是在写一些基础类库时会避免直接引用太多依赖组件。

所以这里是只用微软自带的DI(Microsoft.Extensions.DependencyInjection)去处理。

现在有一个接口和两个实现类。

public interface IDemoService{    string Get();}

public class DemoServiceA : IDemoService
{
public string Get()
{
return "Service A";
}
}

public class DemoServiceB : IDemoService
{
public string Get()
{
return "Service B";
}
}

常规的方法,我们先在Startup中的ConfigureServices方法中添加我们的service。

public voID ConfigureServices(IServiceCollection services){    services.AddSingleton();    services.AddSingleton();
services.AddMvc();

}

然后在控制器中使用

private IDemoService _serviceA;

private IDemoService _serviceB;

public ValuesController(IDemoService serviceA,IDemoService serviceB)
{
_serviceA = serviceA;
_serviceB = serviceB;
}

// GET API/values
[httpGet]
public string Get()
{
return $"{_serviceA.Get()}-{_serviceB.Get()}";
}

我们的预期结果是:Service A-Service B,可是上面代码的实际结果却并不像我们想的那么简单!!

可以看到这里输出的都是Service B,连Service A的影子都没有看到。

其实,从代码都可以看出来,它只能拿到其中一个Service的实现类!

那么我们要息怎样处理才能达到我们想要的效果呢?

其实思路比较简单,上面导致不能拿到对应实现类,本质上来讲应该说是它区分不了那个才是想要的!我们想个办法让它能区分就好了。

给我们的Service起个别名!

先是Startup中的ConfigureServices方法。

public voID ConfigureServices(IServiceCollection services){    services.AddSingleton();    services.AddSingleton();
services.AddSingl<a href="https://www.jb51.cc/tag/eto/" target="_blank" >eto</a>n(factory =>{    Func<string,IDemoService> accesor = key =>    {        if (key.Equals("ServiceA"))        {            return factory.GetService<DemoServiceA>();        }        else if (key.Equals("ServiceB"))        {            return factory.GetService<DemoServiceB>();        }        else        {            throw new ArgumentException($"Not Support key : {key}");        }    };    return accesor;});services.AddMvc();

}

这里并没有直接向上面那样一次性指定接口和对应的实现类,而是用了AddSingleton的另一个重载方法。

先将实现类注册一下然后再注册一下Func

先来说说这个Func里面的string和IDemoService都分别代表什么。

string 毫无疑问就是我们上面说到的别名IDemoService 这个就是我们要用的Service

核心在于,factory参数是IServiceProvIDer类型的!所以我们可以根据这个factory去找到我们前面注册的实现类。这样解释一下,是不是就清晰了呢?

然后再来看看在控制器上面怎么用。

private IDemoService _serviceA;

private IDemoService _serviceB;

private Readonly Func<string,IDemoService> _serviceAccessor;

public ValuesController(Func<string,IDemoService> serviceAccessor)
{
this._serviceAccessor = serviceAccessor;

_serviceA = _serviceAccessor("ServiceA");_serviceB = _serviceAccessor("ServiceB");

}

// GET API/values
[httpGet]
public string Get()
{
return $"{_serviceA.Get()}-{_serviceB.Get()}";
}

最后看看结果是不是和我们的预期一样。

结果与预期一致。

一对一,或许是最好的方法,也是最为理想的,这样能避开很多不必要的问题。但是现实中总会出现特殊情况,面对这些特殊情况,我们也是需要能够重容的面对。

如果您有更好的处理方法,也可以留言讨论。

文中的示例代码 href="https://github.com/catcherwong/Demos/tree/master/src/DIDemo">DIDemo

总结

以上是内存溢出为你收集整理的在.NET Core中处理一个接口多个不同实现的依赖注入问题全部内容,希望文章能够帮你解决在.NET Core中处理一个接口多个不同实现的依赖注入问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1256006.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存