大家好,我是深山踏红叶,今天我们来聊一聊 ASP.NET Core中的 FromKeyedServices,它是在 .Net 8 中引入的。这一特性允许通过键(如字符串或枚举)来注册和检索依赖注入(DI)服务,从而支持一对多的依赖注入模式,个人感觉最主要的还是不用写 构造函数注入了 。下面我们来看一下键控依赖注入的使用。
普通构造函数注入
构造函数注入是 ASP.NET Core 中最常用的依赖项注入方式。服务通过构造函数参数添加,并在运行时从服务容器中解析。
获取当前时间
- 1. 定义服务接口:public interface IDateTime
{
DateTime Now { get; }
} - 2. 实现服务接口:public class SystemDateTime : IDateTime
{
public DateTime Now => DateTime.Now;
} - 3. 注册服务到服务容器:public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton();
services.AddControllersWithViews();
} - 4. 在控制器中使用:public class HomeController : Controller
{
private readonly IDateTime _dateTime;
public HomeController(IDateTime dateTime)
{
_dateTime = dateTime;
}
public IActionResult Index()
{
var serverTime = _dateTime.Now;
if (serverTime.Hour < 12)
{
ViewData["Message"] = "It's morning here - Good Morning!";
}
else if (serverTime.Hour < 17)
{
ViewData["Message"] = "It's afternoon here - Good Afternoon!";
}
else
{
ViewData["Message"] = "It's evening here - Good Evening!";
}
return View();
}
}
使用FromServices的操作注入
FromServices 属性允许直接将服务注入到操作方法中,而无需通过构造函数注入。
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet(Name = "GetWeatherForecast")]
public IActionResult About([FromServices] IDateTime dateTime)
{
return Content($"Current server time: {dateTime.Now}");
}
}
使用FromKeyedServices的操作注入
FromKeyedServices 属性允许从 DI 容器中访问键控服务。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton("big");
builder.Services.AddKeyedSingleton("small");
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
public interface ICache
{
object Get(string key);
}
public class BigCache : ICache
{
public object Get(string key) => $"Resolving {key} from big cache.";
}
public class SmallCache : ICache
{
public object Get(string key) => $"Resolving {key} from small cache.";
}
[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
[HttpGet("big")]
public ActionResult<object> GetBigCache([FromKeyedServices("big")] ICache cache)
{
return cache.Get("data-mvc");
}
[HttpGet("small")]
public ActionResult<object> GetSmallCache([FromKeyedServices("small")] ICache cache)
{
return cache.Get("data-mvc");
}
}
从控制器访问设置
从控制器访问应用或配置设置是一种常见模式。推荐使用选项模式(Options Pattern)来管理设置。
- 1. 定义配置类:public class SampleWebSettings
{
public string Title { get; set; }
public int Updates { get; set; }
} - 2. 注册配置类到服务容器:public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton();
services.Configure(Configuration);
services.AddControllersWithViews();
} - 3. 从 JSON 文件加载配置:public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("samplewebsettings.json",
optional: false,
reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
});
} - 4. 在控制器中使用配置:public class SettingsController : Controller
{
private readonly SampleWebSettings _settings;
public SettingsController(IOptionssettingsOptions)
{
_settings = settingsOptions.Value;
}
public IActionResult Index()
{
ViewData["Title"] = _settings.Title;
ViewData["Updates"] = _settings.Updates;
return View();
}
}
参考:在 ASP.NET Core 中将依赖项注入到控制器
总结
键控依赖注入是 ASP.NET Core 中一个强大的功能,尤其适用于需要灵活切换实现的场景。