gpt4 book ai didi

c# - 如何从类中访问 ASP.NET Core DI 容器

转载 作者:行者123 更新时间:2023-11-30 23:17:40 25 4
gpt4 key购买 nike

我正在使用 Asp.net Core 学习 IoC 和 DI。我已经设置了我的 DbContext 和其他要注入(inject)到我的 Controller 中的类。

目前我的 startup.cs 看起来像这样:

// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));


services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 5;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
}).AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

services.AddMvc();

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

如您所见,我正在注入(inject) AppSettings 类。我可以像这样访问此类:

private readonly AppSettings _appSettings;

public HomeController(UserManager<ApplicationUser> userManager,
ApplicationDbContext dbContext,
ViewRender view,
IHostingEnvironment env,
IOptions<AppSettings> appSettings
)
{
}

将其传递到 Controller 的构造函数中工作正常。

但是我需要访问一个类中的 AppSettings,并且希望有一个静态方法可以用来将该类注入(inject)到任何随机类中。这可能吗?还是我需要将其注入(inject) Controller 并将其传递给其他类?

最佳答案

防止注入(inject) IOptions<T>应用程序类中的依赖项。这样做充满了问题,如所述here .

同样是一个AppSettings的注入(inject)into classes 是一个问题,因为这意味着所有类都注入(inject)了所有配置值,而它们只使用其中的一个或两个值。这使得这些类更难测试,并且更难弄清楚此类实际需要哪个配置值。它还将配置验证推送到您的应用程序内部,这使您的应用程序更加脆弱;当缺少配置值时,您会在很久以后发现,而不是在应用程序启动时发现。

一个类应该在它的构造函数中指定它需要的东西,并且不应该通过其他类传递这些依赖关系。这适用于注入(inject)的组件和配置值。这意味着如果一个类需要特定的配置值,它应该在其构造函数中指定该值,并且仅指定该值。

更新

包含此 SendVerification() 的“电子邮件类”您提到的方法对我来说似乎是一个应用程序组件。由于该类发送实际邮件,因此它需要所有这些邮件配置设置;不是 Controller !所以这些设置应该直接注入(inject)到那个组件中。但同样,不要向该类注入(inject)任何通用内容(例如 IOptions<T>AppSettingsIConfiguration )。 1 尽可能具体说明该类需要什么,以及 2. 确保在应用程序启动时读取配置值,这样您可以让应用程序在启动时快速失败。

所以我想象你的“邮件类”由如下抽象定义:

public interface IVerificationSender
{
void SendVerification(User user);
}

这允许您的 Controller 依赖于此抽象。请注意,任何组件都不应创建应用程序组件本身的依赖项。这是一种称为 Control Freak 的反模式(参见 this book)。

// Controller that depends on the IVerificationSender abstraction
public class HomeController : Controller
{
private readonly IVerificationSender verificationSender;
public HomeController(IVerificationSender verificationSender, ...) {
this.verificationSender = verificationSender;
}

public void SomeAction() {
this.verificationSender.SendVerification(user);
}
}

现在我们有一个 IVerificationSender使用邮件发送消息的实现(这是您的“邮件类”)。该类(class)伴随着 Parameter Object它包含此类所需的所有配置值(但绝对仅此而已)。

// Settings class for the IVerificationSender implementation
public class SmtpVerificationSenderSettings
{
public string MailHost { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool EnableSsl { get; set; }
// etc
}

public class EmailVerificationSender : IVerificationSender
{
private readonly SmtpVerificationSenderSettings settings;
public EmailVerificationSender(SmtpVerificationSenderSettings settings) {
if (settings == null) throw new ArgumentNullException("settings");
this.settings = settings;
}

public void SendVerification(User user) {
using (var client = new SmtpClient(this.settings.MailHost, 25)) {
smtpClient.EnableSsl = this.settings.EnableSsl;
using (MailMessage mail = new MailMessage()) {
mail.From = new MailAddress("info@foo", "MyWeb Site");
mail.To.Add(new MailAddress(user.Email));
mail.Body = $"Hi {user.Name}, Welcome to our site.";
client.Send(mail);
}
}
}
}

使用这种方法,注册 Controller 和 EmailVerificationSender应该是微不足道的。你甚至可以使用这个 SmtpVerificationSenderSettings作为从配置文件加载的可序列化对象:

IConfiguration config = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("settubgs.json");
.Build();

var settings = config.GetSection("SmtpVerificationSenderSettings")
.Get<SmtpVerificationSenderSettings>();

// Verify the settings object
if (string.IsNullOrWhiteSpace(settings.MailHost)
throw new ConfigurationErrorsException("MailSettings MailHost missing.");
if (string.IsNullOrWhiteSpace(settings.MailHost)
throw new ConfigurationErrorsException("MailSettings UserName missing.");
// etc

// Register the EmailVerificationSender class
services.AddSingleton<IVerificationSender>(new EmailVerificationSender(settings));

哪里settings.json可能如下所示:

{
"SmtpVerificationSenderSettings": {
"MailHost" : "localhost",
"UserName" : "foobar",
// etc
}
}

关于c# - 如何从类中访问 ASP.NET Core DI 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41304249/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com