c# - 如何使用 MS.DI 和 .NET Core 从静态方法重构为依赖注入(inject)?

标签 c# asp.net-mvc entity-framework asp.net-core dependency-injection

我正在将项目从 .Net Framework 迁移到 .Net Core。在现有的项目中,我们有一个实用程序类,其中包含一些功能,如下所示:

public static class BudgetUtilities
{
    public static decimal CalculateBudgetRemaining(string fiscalYear = null)
    {
        if (string.IsNullOrWhiteSpace(fiscalYear))
            fiscalYear = DateTime.Now.GetFiscalYear().ToString();

        using (AppContext _context = new AppContext())
        {
            FiscalYearBudget currentBudget = _context.FiscalYearBudgets.Find(fiscalYear);

            return currentBudget.BudgetAllocation - currentBudget.ExpenditureToDate;
        }
    }

    // other functions removed for brevity
}

然后我可以使用 BudgetUtilities.CalculateBudgetRemaining() 在其他任何地方引用它。非常简单明了。

当将此函数迁移到 .Net Core 时,我需要使用依赖注入(inject),因此我通过删除 static 修饰符(因为静态构造函数不能有参数)并将 AppContext 注入(inject)到构造函数中来修改该类:

public class BudgetUtilities
{
    private readonly AppContext _context;

    public BudgetUtilities(AppContext context)
    {
        _context = context;
    }

    public decimal CalculateBudgetRemaining(string financialYear = null)
    {
        if (string.IsNullOrWhiteSpace(fiscalYear))
            fiscalYear = DateTime.Now.GetFiscalYear().ToString();

        FiscalYearBudget currentBudget = _context.FiscalYearBudgets.Find(fiscalYear);

        return currentBudget.BudgetAllocation - currentBudget.ExpenditureToDate;
    }
}

然后我尝试通过执行以下操作来调用我的代码:

BudgetUtilities utils = new BudgetUtilities();
decimal remaining = utils.CalculateBudgetRemaining();

但是如果不在构造函数中提供 AppContext,我就无法创建 BudgetUtilities 的新实例,这是有意义的。此应用程序中的每个方法都在某个时刻由 Controller 操作启动,并且我知道 DbContext 应该是短暂的,因此我假设将上下文从头到尾传递到此 BudgetUtilities 类初始 Controller 是一个坏主意。

我能看到的唯一其他选项是继续从引用 CalculateBudgetRemaining() 的地方返回调用堆栈,并继续添加构造函数注入(inject),直到到达 Controller ,但这不是我必须像这样注入(inject)唯一的类,因此我的构造函数在链上会变得非常臃肿,这将使我的 ConfigureServices() 方法也变得臃肿。

我确信有一种简单的方法可以做到这一点,但我就是看不到它。

最佳答案

不要手动创建新的 BudgetUtilities 实例,该类型也应该在 DI 框架中注册,最好是接口(interface):

public interface IBudgetUtilities
{
    decimal CalculateBudgetRemaining(string financialYear);
}

public class BudgetUtilities : IBudgetUtilities

然后在 Startup.cs 中:

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddScoped<IBudgetUtilities, BudgetUtilities>();
}

然后它可以被注入(inject)到任何需要它的类中,例如 Controller :

public class YourController : Controller
{
    private readonly IBudgetUtilities _utils;

    public YourController(IBudgetUtilities utils)
    {
        _utils = utils;
    }

    public ActionResult YourMethod()
    {
        //...
        decimal remaining = _utils.CalculateBudgetRemaining();
    }
}

默认情况下,注册的 DbContexts 具有限定的生命周期,这意味着单个实例用于整个 HTTP 请求。

关于c# - 如何使用 MS.DI 和 .NET Core 从静态方法重构为依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61323366/

相关文章:

c# - Web 服务的空响应 (WSDL SOAP)

c# - 使用用户实现的 zip 函数合并不同大小的数组

c# - 如何在 Application_BeginRequest 中执行击中网络服务器的第一个请求的部分代码?

c# - 使用 entityFramework 插入包含 IEnumerable 属性的模型

.net - 实现 LINQ to Entities 不受支持的方法

c# - 使用外键对多个表进行分组

c# - 如何在没有页面重新加载的情况下调用页面方法?

c# - 将特定异常作为默认值传递

asp.net-mvc - 存储库模式和 IQueryable<T> 的性能

sql-server - IIS 和 SQL Server 之间的连接字符串