百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

C# 中的 Scrutor — 升级依赖注入的 3 个简单技巧

bigegpt 2024-08-15 20:01 3 浏览


在组织依赖关系时,C# 中的依赖关系注入是救命稻草,尤其是在更复杂的 ASP.NET Core 应用程序中。如果你已经熟悉 IServiceCollection,或者只是想尽可能地接近已经提供的 DI 产品,那么 C# 中的 Scrutor 是一个很棒的增强功能。

在本文中,我将简要介绍 C# 中的依赖项注入和 Scitor。但从那里开始,我们将直接进入 3 个技巧,您可以将其与 Scrutor 一起使用,这些技巧可能对您的应用程序非常有帮助!

C# 中的 Scrutor 是什么?

Scrutor 是 C# 中功能强大的 NuGet 包,可增强依赖项注入。它简化了依赖项的注册和解析,使你能够更轻松地管理和组织代码。

依赖注入是一种常用的应用程序配置方法,可促进松耦合并提高可测试性和可维护性。它涉及将依赖项注入到类中,而不是直接在类中创建它们。这意味着创建依赖项的责任不归需要它的类所有,而是由调用堆栈中的某个人拥有。最终,这会将几乎所有的依赖项创建推到应用程序的入口点,使其变得笨拙。但是依赖注入框架有助于清理和组织所有这些逻辑。

Scrutor 通过提供一种简单直观的方法来注册和解析依赖关系,将这一概念向前推进了一步。使用 Scrutor,您不再需要手动逐个注册每个依赖项。相反,您可以使用约定和属性来自动执行该过程。

1 — 使用 Scrutor 进行注册和解决

为了说明如何在 C# 中使用 Scrutor 进行注册和解析,让我们考虑一个简单的场景。假设我们有一个应用程序,需要使用不同的数据存储库,例如 UserRepository 和 ProductRepostiory。

首先,我们需要在项目中安装 Scrutor NuGet 包。打开包管理器控制台并运行以下命令:

Install-Package Scrutor

接下来,我们需要定义我们的仓库及其相应的接口。这个例子基本上是空的,但我们稍后会提到这些:

public interface IUserRepository 
{
// Interface methods
}

public class UserRepository : IUserRepository
{
// Implementation
}

public interface IProductRepository
{
// Interface methods
}

public class ProductRepository : IProductRepository
{
// Implementation
}

现在,让我们使用 Scrutor 连接我们的依赖项。在启动代码(例如 ASP.NET Core 中的 ConfigureServices 方法中)中,添加以下代码:

services.Scan(scan => scan 
.FromAssemblyOf<Startup>()
.AddClasses(classes => classes.AssignableToAny(
typeof(IUserRepository),
typeof(IProductRepository)))
.AsImplementedInterfaces()
.WithScopedLifetime());

此代码使用 Scrutor 中的 Scan 方法扫描包含 Startup 类的程序集。然后,它会筛选出可分配给 IUserRepository 或 IProductRepository 接口的类。最后,它映射了这些接口的实现,并将它们注册到各自的接口中。

现在,我们可以将这些依赖项注入到我们的类中。例如,假设我们有一个需要 IUserRepository 的 UserService 类:

public class UserService 
{
private readonly IUserRepository _userRepository;

public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}

// Rest of the class implementation
}

通过在构造函数中将 IUserRepository 声明为依赖项,Scrutor 和 IServiceCollection 将自动解析并注入 UserRepository 实例。

2 — 装饰器模式 — 服务日志记录示例

想象一下,你有一个服务接口和一个实现。您希望记录每个方法调用的入口和出口,而不会因日志记录问题而污染其业务逻辑。IServiceMyServiceMyService

首先,定义接口及其实现:IService

public interface IService 
{
void DoWork();
}

public class MyService : IService
{
public void DoWork()
{
// Business logic here
}
}

接下来,创建一个实现 .此类将包装实际服务,并围绕委托方法调用添加日志记录:LoggingDecoratorIService

public class LoggingDecorator : IService 
{
private readonly IService _decorated;
private readonly ILogger<LoggingDecorator> _logger;

public LoggingDecorator(IService decorated, ILogger<LoggingDecorator> logger)
{
_decorated = decorated;
_logger = logger;
}

public void DoWork()
{
_logger.LogInformation("Starting work.");
_decorated.DoWork();
_logger.LogInformation("Finished work.");
}
}

现在,使用 Scrutor 在配置服务的任何位置注册服务及其装饰器:Startup.cs

public void ConfigureServices(IServiceCollection services) 
{
// Register the base service
services.AddScoped<IService, MyService>();

// Use Scrutor to apply the decorator
services.Decorate<IService, LoggingDecorator>();

// Make sure to register the ILogger or ILogger<T> dependencies if not already done

}

此设置使用 Scrutor 将注册包装为 .解析时,DI 容器将提供 的实例,而 的实例又包装 的实例。此方法通过将日志记录逻辑保留在业务逻辑之外来实现关注点的分离。

3 — 服务实现的功能切换

当我们构建复杂的系统时,经常会出现一些类似功能标志的东西。这些允许我们根据配置采用不同的代码路径,而不必重新编译和部署整个应用程序。在某些情况下,这不仅仅是选择不同的代码路径,而是交换某些东西的整个实现!

让我们一起尝试一个例子!假设您有一个包含多个实现的接口:(一个新的实验性功能)和(当前的稳定功能)。您希望在运行时根据配置标志在这些实现之间切换。

首先,定义接口及其实现:IFeatureService

public interface IFeatureService 
{
void ExecuteFeature();
}

public class NewFeatureService : IFeatureService
{
public void ExecuteFeature()
{
// New feature logic
}
}

public class StandardFeatureService : IFeatureService
{
public void ExecuteFeature()
{
// Standard feature logic
}
}

接下来,您需要一种方法来根据功能切换设置确定要使用的实现。这可以是 、数据库设置或任何其他配置源中的值。appsettings.json

现在,使用 Scrutor 根据功能切换动态注册相应的服务实现:

public void ConfigureServices(IServiceCollection services) 
{
// Assume GetFeatureToggleValue() retrieves the current feature toggle setting
var useNewFeature = GetFeatureToggleValue("UseNewFeature");

// Dynamically register the appropriate implementation based on the feature toggle
if (useNewFeature)
{
services.AddScoped<IFeatureService, NewFeatureService>();
}
else
{
services.AddScoped<IFeatureService, StandardFeatureService>();
}

// Optional: You could combine this with the previous example
// to use the decorator pattern too!
// services.Decorate\<IFeatureService, FeatureServiceProxy>();
}

private bool GetFeatureToggleValue(string featureName)
{
// This method would typically check your
// configuration source to determine if the feature is enabled
// For simplicity, this is just a placeholder
return false; // or true based on actual configuration
}

采取这样的方法可以帮助我们:

  • 灵活性:允许应用程序在功能实现之间切换,而无需重新部署。只需更改配置即可启用或禁用功能。

  • 在生产环境中测试:可以通过为这些用户打开功能,在具有有限用户集的生产环境中测试新功能。

  • 逐步推出:帮助逐步推出功能,以监控影响并确保在更广泛发布之前的稳定性。

  • 风险缓解:如果新功能出现问题,可以快速恢复到旧实现,从而最大限度地减少停机时间和对用户的影响。

在 C# 中总结 Scrutor

在本文中,我为您提供了 3 个在 C# 中使用 Scrutor 进行依赖注入的简单技巧。在简要概述了什么是依赖注入以及 Scrutor 如何适应它之后,我们直接进入了我们的示例。我们看到了程序集扫描,如何装饰依赖项,甚至如何考虑功能标记整个实现!

如果你喜欢我的文章,请给我一个赞!谢谢

相关推荐

了解Linux目录,那你就了解了一半的Linux系统

大到公司或者社群再小到个人要利用Linux来开发产品的人实在是多如牛毛,每个人都用自己的标准来配置文件或者设置目录,那么未来的Linux则就是一团乱麻,也对管理造成许多麻烦。后来,就有所谓的FHS(F...

Linux命令,这些操作要注意!(linux命令?)

刚玩Linux的人总觉得自己在演黑客电影,直到手滑输错命令把公司服务器删库,这才发现命令行根本不是随便乱用的,而是“生死簿”。今天直接上干货,告诉你哪些命令用好了封神!喜欢的一键三连,谢谢观众老爷!!...

Linux 命令速查手册:这 30 个高频指令,拯救 90% 的运维小白!

在Linux系统的世界里,命令行是强大的武器。对于运维小白而言,掌握一些高频使用的Linux命令,能极大提升工作效率,轻松应对各种系统管理任务。今天,就为大家奉上精心整理的30个Linu...

linux必学的60个命令(linux必学的20个命令)

以下是Linux必学的20个基础命令:1.cd:切换目录2.ls:列出文件和目录3.mkdir:创建目录4.rm:删除文件或目录5.cp:复制文件或目录6.mv:移动/重命名文件或目录7....

提高工作效率的--Linux常用命令,能够决解95%以上的问题

点击上方关注,第一时间接受干货转发,点赞,收藏,不如一次关注评论区第一条注意查看回复:Linux命令获取linux常用命令大全pdf+Linux命令行大全pdf为什么要学习Linux命令?1、因为Li...

15 个实用 Linux 命令(linux命令用法及举例)

Linux命令行是系统管理员、开发者和技术爱好者的强大工具。掌握实用命令不仅能提高效率,还能解锁Linux系统的无限潜力,本文将深入介绍15个实用Linux命令。ls-列出目录内容l...

Linux 常用命令集合(linux常用命令全集)

系统信息arch显示机器的处理器架构(1)uname-m显示机器的处理器架构(2)uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DM...

Linux的常用命令就是记不住,怎么办?

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux常用文件操作命令(linux常用文件操作命令有哪些)

ls命令在Linux维护工作中,经常使用ls这个命令,这是最基本的命令,来写几条常用的ls命令。先来查看一下使用的ls版本#ls--versionls(GNUcoreutils)8.4...

Linux 常用命令(linux常用命令)

日志排查类操作命令查看日志cat/var/log/messages、tail-fxxx.log搜索关键词grep"error"xxx.log多条件过滤`grep-E&#...

简单粗暴收藏版:Linux常用命令大汇总

号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部下午好,我的网工朋友在Linux系统中,命令行界面(CLI)是管理员和开发人员最常用的工具之一。通过命令行,用户可...

「Linux」linux常用基本命令(linux常用基本命令和用法)

Linux中许多常用命令是必须掌握的,这里将我学linux入门时学的一些常用的基本命令分享给大家一下,希望可以帮助你们。总结送免费学习资料(包含视频、技术学习路线图谱、文档等)1、显示日期的指令:d...

Linux的常用命令就是记不住,怎么办?于是推出了这套教程

1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...

Linux的30个常用命令汇总,运维大神必掌握技能!

以下是Linux系统中最常用的30个命令,精简版覆盖日常操作核心需求,适合快速掌握:一、文件/目录操作1.`ls`-列出目录内容`ls-l`(详细信息)|`ls-a`(显示隐藏文件)...

Linux/Unix 系统中非常常用的命令

Linux/Unix系统中非常常用的命令,它们是进行文件操作、文本处理、权限管理等任务的基础。下面是对这些命令的简要说明:**文件操作类:*****`ls`(list):**列出目录内容,显...