博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
巧用 Lazy 解决.NET Core中的循环依赖关系
阅读量:4033 次
发布时间:2019-05-24

本文共 2252 字,大约阅读时间需要 7 分钟。

原文作者: Thomas Levesque 原文链接:https://thomaslevesque.com/2020/03/18/lazily-resolving-services-to-fix-circular-dependencies-in-net-core/

循环依赖的问题

在构建应用程序时,良好的设计应该应避免服务之间的循环依赖, 循环依赖是指某些组件直接或间接相互依赖,比如下面这样

如果您不小心在.NET Core应用程序使用了依赖项注入,并且引入了以下循环依赖关系,你要知道的是,项目启动会报一个循环依赖的错误,因为依赖关系周期中涉及的组件的解析将失败,比如,你具有以下组件:

•A服务,它实现了接口IA并取决于IB•B服务,它实现了接口IB并取决于IC•C服务,它实现了接口IC并取决于IA

System.InvalidOperationException: A circular dependency was detected for the service of type 'Demo.IA'.

所以应该去避免这些设计。

注入 IServiceProvider

但是,当实际应用程序达到一定程度的复杂性时,有时可能很难避免,有一天不小心给服务添加了一个依赖项,启动报错了,事情突然浮出水面, 因此,您面临一个选择:重构,来解决循环依赖的问题,理想情况下,应该去选择重构,但是实际情况中,可能项目比较紧,可能没有时间重构代码,因为要做完整的回归测试。

一种方法是将注入 IServiceProvider 到您的类中,并services.GetRequiredService()在需要使用时使用T,例如,C我前面提到的类,最初可能看起来像这样:

class C : IC{    private readonly IA _a;    public C(IA a)    {        _a = a;    }    public void Bar()    {        ...        _a.Foo()        ...    }}

为了避免依赖性循环,可以注入 IServiceProvider, 然后这样重写它:

class C : IC{    private readonly IServiceProvider _services;    public C(IServiceProvider services)    {        _services = services;    }    public void Bar()    {        ...        var a = _services.GetRequiredService
(); a.Foo(); ... }}

由于在构建IA时不再需要解决问题C,因此中断了循环(至少在构建过程中),并解决了问题,但是,我不太喜欢这种方法,因为这样强制依赖了IOC,如果我使用了 Autofac 等,另一个问题是我很难看到类的依赖关系,它不明显。

巧用 Lazy<T>

下边的方法我利用了Lazy类,需要添加一个 IServiceCollection 的扩展,新建一个静态类

public static IServiceCollection AddLazyResolution(this IServiceCollection services){    return services.AddTransient(        typeof(Lazy<>),        typeof(LazilyResolved<>));}private class LazilyResolved
: Lazy
{ public LazilyResolved(IServiceProvider serviceProvider) : base(serviceProvider.GetRequiredService
) { }}

然后再 Startup.cs 中的 ConfigureServices 方法中这样写

services.AddLazyResolution();

在依赖的类中IA,注入Lazy,当您需要使用时IA,只需访问lazy的值 Value 即可:

class C : IC{    private readonly Lazy
_a; public C(Lazy
a) { _a = a; } public void Bar() { ... _a.Value.Foo(); ... }}

注意:不要访问构造函数中的值,保存Lazy即可 ,在构造函数中访问该值,这将导致我们试图解决的相同问题。

这个解决方案不是完美的,但是它解决了最初的问题却没有太多麻烦,并且依赖项仍然在构造函数中明确声明,我可以看到类之间的依赖关系。

最后

欢迎扫码关注我们的公众号 【全球技术精选】,专注国外优秀博客的翻译和开源项目分享,也可以添加QQ群 897216102

转载地址:http://dbudi.baihongyu.com/

你可能感兴趣的文章
01Java基础语法-13. if分支语句的灵活使用
查看>>
01Java基础语法-15.for循环结构
查看>>
01Java基础语法-16. while循环结构
查看>>
01Java基础语法-17. do..while循环结构
查看>>
01Java基础语法-18. 各种循环语句的区别和应用场景
查看>>
01Java基础语法-19. 循环跳转控制语句
查看>>
Django框架全面讲解 -- Form
查看>>
socket,accept函数解析
查看>>
今日互联网关注(写在清明节后):每天都有值得关注的大变化
查看>>
”舍得“大法:把自己的优点当缺点倒出去
查看>>
[今日关注]鼓吹“互联网泡沫,到底为了什么”
查看>>
[互联网学习]如何提高网站的GooglePR值
查看>>
[关注大学生]求职不可不知——怎样的大学生不受欢迎
查看>>
[关注大学生]读“贫困大学生的自白”
查看>>
[互联网关注]李开复教大学生回答如何学好编程
查看>>
[关注大学生]李开复给中国计算机系大学生的7点建议
查看>>
[关注大学生]大学毕业生择业:是当"鸡头"还是"凤尾"?
查看>>
[茶余饭后]10大毕业生必听得歌曲
查看>>
gdb调试命令的三种调试方式和简单命令介绍
查看>>
C++程序员的几种境界
查看>>