我可以在控制器中进行DI app设置,就像这样
private IOptions<AppSettings> appSettings;
public CompanyInfoController(IOptions<AppSettings> appSettings)
{
this.appSettings = appSettings;
}
但是如何在我的自定义类中使用DI
private IOptions<AppSettings> appSettings;
public PermissionFactory(IOptions<AppSettings> appSetting)
{
this.appSettings = appSettings;
}
我在Startup.cs中的注册是
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
答案 0 :(得分:3)
在DI中注册您的自定义类,就像在ConfigureServices
方法中注册其他依赖项一样,例如:
services.AddTransient<PermissionFactory>();
(而不是AddTransient
,您可以使用AddScoped
或您需要的任何其他生命周期
然后将此依赖项添加到控制器的构造函数中:
public CompanyInfoController(IOptions<AppSettings> appSettings, PermissionFactory permFact)
现在,DI了解PermissionFactory
,可以实例化它并将其注入您的控制器。
如果您想在PermissionFactory
方法中使用Configure
,只需将其添加到其参数列表中:
Configure(IApplicationBuilder app, PermissionFactory prov)
Aspnet会做它的魔法并在那里注入课程。
如果你想在代码深处的某个地方实例化PermissionFactory
,你也可以用一种讨厌的方式做到这一点 - 在IServiceProvider
类中存储对Startup
的引用:
internal static IServiceProvider ServiceProvider { get;set; }
Configure(IApplicationBuilder app, IServiceProvider prov) {
ServiceProvider = prov;
...
}
现在您可以像这样访问它:
var factory = Startup.ServiceProvider.GetService<PermissionFactory>();
再一次,DI会负责将IOptions<AppSettings>
注入PermissionFactory
。
答案 1 :(得分:2)
我建议不要传递AppSettings
。一个班级不应该依赖于某些含糊不清的东西 - 它应该完全取决于它需要什么,或者接近它。 ASP.NET Core可以更容易地摆脱依赖于AppSettings
的旧模式。如果您的课程取决于AppSettings
,那么您无法从构造函数中看到它依赖的内容。它可能取决于任何关键。如果它依赖于更具体的接口,那么它的依赖性更清晰,更明确,并且您可以在单元测试时模拟该接口。
您可以创建一个界面,其中包含您的类所需的特定设置(或不太具体但不太宽泛的设置)和实现它的类 - 例如,
public interface IFooSettings
{
string Name { get; }
IEnumerable Foos { get; }
}
public interface IFoo
{
string Color { get; }
double BarUnits { get; }
}
public class FooSettings : IFooSettings
{
public string Name { get; set; }
public List<Foo> FooList { get; set; }
public IEnumerable Foos
{
get
{
if (FooList == null) FooList = new List<Foo>();
return FooList.Cast<IFoo>();
}
}
}
public class Foo : IFoo
{
public string Color { get; set; }
public double BarUnits { get; set; }
}
然后添加一个.json文件,fooSettings.json:
{
"FooSettings": {
"Name": "MyFooSettings",
"FooList": [
{
"Color": "Red",
"BarUnits": "1.5"
}, {
"Color": "Blue",
"BarUnits": "3.14159'"
}, {
"Color": "Green",
"BarUnits": "-0.99999"
}
]
}
}
然后,在Startup()
(在Startup.cs中)我们指定进入Configuration
的内容,添加fooSettings.json:
var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("config.json")
.AddJsonFile($"config.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("fooSettings.json");
最后,在ConfigureServices()
(也在Startup.cs中)告诉它加载FooSettings
的实例,将其转换为IFooSetting
s(因此属性显示为只读)并且为IFooSettings
上的所有依赖项提供单个实例:
var fooSettings = (IFooSettings)ConfigurationBinder.Bind<FooSettings>(
Configuration.GetConfigurationSection("FooSettings"));
services.AddInstance(typeof (IFooSettings), fooSettings);
现在你的类 - 控制器,过滤器或DI容器创建的任何其他东西 - 都可以依赖IFooSettings
,它将从.json文件提供。但你可以模拟IFooSettings
进行单元测试。
Original blog post - 它是我的,所以我不会剽窃。
答案 2 :(得分:1)
您也可以在非控制器类中执行依赖注入。
在startup
课程中
public class Startup
{
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
// register other dependencies also here
services.AddInstance<IConfiguration>(Configuration);
}
}
现在,在您的自定义类中,让构造函数接受IConfiguration
private IConfiguration configuration;
public PermissionFactory(IConfiguration configuration)
{
this.configuration = configuration;
}
public void SomeMethod()
{
var someSection = this.configuration.GetSection("SomeSection");
var someValue= this.configuration.Get<string>("YourItem:SubItem");
}
答案 3 :(得分:0)
如果您希望DI对操作过滤器引用Action filters, service filters and type filters in ASP.NET 5 and MVC 6服务过滤器部件。