[英].Net core 2.0 console program got null value when running `serviceProvider.GetService<Application>();`?
The following .Net core 2.0 console application got null value when running serviceProvider.GetService<Application>();
运行serviceProvider.GetService<Application>();
时,以下.Net Core 2.0控制台应用程序的值为空serviceProvider.GetService<Application>();
? ?
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
ConfigureServices(services);
var serviceProvider = services.BuildServiceProvider();
var app = serviceProvider.GetService<Application>(); // Got null value
Task.Run(() => app.Run()).Wait();
}
private static void ConfigureServices(IServiceCollection services)
{
ILoggerFactory loggerFactory = new LoggerFactory()
.AddConsole()
.AddDebug();
services.AddSingleton(loggerFactory); // Add first my already configured instance
services.AddLogging(); // Allow ILogger<T>
IConfigurationRoot configuration = GetConfiguration();
services.AddSingleton<IConfigurationRoot>(configuration);
// Support typed Options
services.AddOptions();
services.Configure<MyOptions>(configuration.GetSection("MyOptions")); // Error!
services.AddTransient<Application>();
}
private static IConfigurationRoot GetConfiguration()
{
return new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddXmlFile("App.config", optional: true).Build();
}
public class MyOptions
{
public string Name { get; set; }
}
public class Application
{
ILogger _logger;
MyOptions _settings;
public Application(ILogger<Application> logger, IOptions<MyOptions> settings)
{
_logger = logger;
_settings = settings.Value;
}
public async Task Run()
{
try
{
_logger.LogInformation($"This is a console application for {_settings.Name}");
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
}
}
}
I think it looks good, you just need to provide a singleton for your options. 我认为它看起来不错,您只需要提供一个单例即可。
var options = new MyOptions();
configuration.GetSection("MyOptions").Bind(options);
services.AddSingleton<MyOptions>(options);
Then, shift your app to use that singleton. 然后,转移您的应用程序以使用该单例。
public Application(ILogger<Application> logger, MyOptions settings)
EDIT: What about IOptions Pattern? 编辑:IOptions模式怎么样?
Seems like others have suggested that you can use that syntax if you import the 1.0.0-rc2-final version of Microsoft.Extensions.Options.ConfigurationExtensions, but that will cascade into other references as well. 似乎其他人建议,如果导入Microsoft.Extensions.Options.ConfigurationExtensions的1.0.0-rc2-final版本,则可以使用该语法,但是它也会级联到其他引用中。 Might not be worth it just to late-bind the options class. 仅仅延迟绑定选项类可能不值得。
All Working (less IOptions) 所有工作(较少的IOptions)
If that's an ok approach, then there is some other code in that section that doesn't function. 如果这是一种好的方法,那么该节中还有其他一些代码将无法正常工作。 Cleaned up version below. 清理了下面的版本。 Hope that helps. 希望能有所帮助。
class Program {
static void Main(string[] args) {
var services = new ServiceCollection();
ConfigureServices(services);
var serviceProvider = services.BuildServiceProvider();
var app = serviceProvider.GetService<Application>(); // Got null value
Task.Run(() => app.Run()).Wait();
}
private static void ConfigureServices(IServiceCollection services) {
ILoggerFactory loggerFactory = new LoggerFactory()
.AddConsole() // Error!
.AddDebug();
services.AddSingleton(loggerFactory); // Add first my already configured instance
services.AddLogging(); // Allow ILogger<T>
IConfigurationRoot configuration = GetConfiguration();
services.AddSingleton<IConfigurationRoot>(configuration);
// Support typed Options
var myOptions = new MyOptions();
configuration.GetSection("MyOptions").Bind(myOptions);
services.AddSingleton<MyOptions>(myOptions);
services.AddTransient<Application>();
}
private static IConfigurationRoot GetConfiguration() {
return new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddXmlFile("App.config", optional: true).Build();
}
public class MyOptions {
public string Name { get; set; }
}
public class Application {
ILogger _logger;
MyOptions _settings;
public Application(ILogger<Application> logger, MyOptions settings) {
_logger = logger;
_settings = settings;
}
public async Task Run() {
try {
_logger.LogInformation($"This is a console application for {_settings.Name}");
} catch (Exception ex) {
_logger.LogError(ex.ToString());
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.