10+ 剃须刀页面代码背后通过依赖注入获取 dbcontexts

10+ razor page code behind get dbcontexts via dependency injection

我开发了一个 C# ASP.NET Core MVC 应用程序,其中包含很多 razor pages。 我的大部分剃须刀页面都使用 日志记录 发送电子邮件 并使用 多个 dbcontextes.

很多 class 看起来像这样:

class A : PageModel
{
        private readonly ADbContext _context;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly IEmailSender _emailSender;
        private readonly ILogger<MyModel> _logger;

        public UpdateModel(ADbContext context,
                            UserManager<ApplicationUser> userManager,
                            IEmailSender emailSender,
                            ILogger<MyModel> logger)
        {
            _context = context;
            _userManager = userManager;
            _emailSender = emailSender;
            _logger = logger;
        }
}

我有 10 多页这样的内容。 当我创建页面时,我必须添加这些字段。所以很多时候。

摆脱大量字段声明的理想方法是什么?一个 base class 继承了我开发的每一个页面模型?但是这个基础 class 将是一个非常通用的基础 class,带有日志记录、电子邮件和上下文,它们实际上彼此并不相似。 每次我声明一个使用它们的 class 时声明这些字段是一个好的架构选择吗?

总的来说,是的,这就是您所做的。您的依赖项正在被注入,这意味着您需要 ivars 来保存它们,并需要一个构造函数来接受它们。它可以感觉并且看起来是重复的,但这实际上是一件好事。它使您的 class 一目了然:您可以一目了然地快速查看 class 具有哪些依赖项。

如果您愿意,可以创建一个基地 class。但是,您应该注意只在基础 class 中包含真正适用于每个推导的内容。危险在于添加并非在所有情况下都实际需要的依赖项,然后现在您有一堆页面加载它们不需要且不使用的依赖项。

在这里你也可以在一定程度上使用抽象。例如,如果每个页面都依赖于一个上下文,但在不同的场景中可能是不同的上下文,你可以将ivar类型设置为DbContext,而不是你的具体上下文类型,然后你可以将其设置为任何有效的DbContext 的推导。您的记录器也是如此。你实际上想要注入 ILogger<MyPageModel>,但你可以在基础 class 上制作 ivar 只是 ILogger,然后它将接受任何记录器。

不过,当您开始这样做时,您会更难确定 classes 的依赖关系,因此这是一个让步。就个人而言,如果存在共享逻辑,我只会使用基 class。如果 base class 的唯一目的是定义一组特定的依赖项,那么它就不值得拥有。

是否适合改用过滤器?您的过滤器依赖项可以通过 DI 注入吗?

https://www.learnrazorpages.com/razor-pages/filters

您还可以通过在需要服务的函数级别直接注入来简化某些 DI 的情况,而不是通过在参数上方添加“[FromService]”在构造函数级别注入:

    [HttpGet]
    public ActionResult OnGetDoSomething([FromServices] IEmailSender emailService)
    {
        // Do something
    }

这样,如果不需要,您就不必实例化这些服务。

这样的事情怎么样?

class A : BasePage {
    public UpdateModel(IServiceProvider provider) : base(provider) {

        // here you can access the base properties

    }
}

class BasePage : PageModel {
    public ADbContext _context { get; set; }
    public UserManager<ApplicationUser> _userManager; { get; set; }
    public IEmailSender _emailSender; { get; set; }
    public ILogger<MyModel> _logger; { get; set; }

    public UpdateModel(IServiceProvider provider) : base(provider) {
        Context = (ADbContext)provider.GetRequiredService(typeof(ADbContext));
        UserManager = (UserManager)provider.GetRequiredService(typeof(UserManager));
        EmailSender = (IEmailSender)provider.GetRequiredService(typeof(IEmailSender));
        Logger = (ILogger)provider.GetRequiredService(typeof(ILogger));
    }
}