Reputation: 4068
Im trying to read the config and populate the custom objects, but I only get LCTools but not LCLog.
I've tried to use .GetSection("LCTools:LCLog")
appsettings.json:
{
"LCTools": {
"LCLog": {
"AppId": 1
}
}
}
Where I read and load config:
public static IApplicationBuilder UseLCLog(this IApplicationBuilder builder, IConfiguration configuration)
{
ILCToolsOptions options = configuration.GetSection("LCTools").GetSection("LCLog").Get<_LCToolsOptions>();
LogManager.Configuration = LCLog.Utility.GetConfiguration(options);
ILoggerFactory factory = builder.ApplicationServices.GetRequiredService<ILoggerFactory>();
factory.AddNLog();
factory.AddProvider(new DbLCLogProvider(options.LCLogOptions.Filter, configuration));
return builder;
}
Classes:
public interface ILCLogBase
{
Func<string, LogLevel, bool> Filter { get; set; }
}
public abstract class LCLogBase : ILCLogBase
{
public Func<string, LogLevel, bool> Filter { get; set; }
}
public interface ILCToolsOptions
{
ILCLogOptions LCLogOptions { get; set; }
}
public class _LCToolsOptions : LCLogBase, ILCToolsOptions
{
public ILCLogOptions LCLogOptions { get; set; }
}
public interface ILCLogOptions : ILCLogBase
{
int AppId { get; set; }
string FileName { get; set; }
string FileLogLevel { get; set; }
string DbLogLevel { get; set; }
string MicrosoftLevel { get; set; }
string ConnectionString { get; set; }
}
public class LCLogOptions : LCLogBase, ILCLogOptions
{
public int AppId { get; set; }
public string FileName { get; set; } = "${basedir}/_Log/${shortdate}.log";
public string FileLogLevel { get; set; } = "Trace";
public string DbLogLevel { get; set; } = "Warn";
public string MicrosoftLevel { get; set; } = "Trace";
public string ConnectionString { get; set; } = Utility.ConnectionString;
}
Upvotes: 2
Views: 307
Reputation: 49779
Your main problem looks like a misunderstanding of how config builder populates option classes. Configuration API while reading all config sources, internally populates a collection of key-values (simply Dictionary<string, string>
), where a key is a config param name with :
used as a delimiter). For your json file that dictionary contains one item {"LCTools:LCLog:AppId": "1"}
configuration.GetSection("LCTools").GetSection("LCLog").Get<_LCToolsOptions>();
The above code means to configuration builder the following: use from dictionary only items with key started from LCTools:LCLog
, take all available configs and map them to public properties of _LCToolsOptions
class using remaining key part for mapping.
Configuration builder doesn't do data deserialization. Instead, it constructs option class using default constructor without any parameters and then tries to set public properties for that class using taken key-values from the specified config path.
And you have nothing as result cause your LCTools:LCLog
section has AppId
key-value, but _LCToolsOptions
class doesn't provide AppId
public property.
If you want to construct option class from data in LCTools:LCLog
section, you should build the LCLogOptions
instance from .GetSection("LCLog")
section:
var options = configuration.GetSection("LCTools")
.GetSection("LCLog")
.Get<LCLogOptions>();
as properties like AppId
are defined in LCLogOptions
.
If you want to build an instance of _LCToolsOptions
, then you need to modify your option class to:
public class _LCToolsOptions : LCLogBase, ILCToolsOptions
{
public ILCLogOptions LCLog { get; set; }
// instead of
// public ILCLogOptions LCLogOptions { get; set; }
}
note, that type need to be changed from interface to specific class, and property name (LCLog
) should reflect the name used in JSON config file.
and then do
var options = configuration.GetSection("LCTools").Get<_LCToolsOptions>();
Upvotes: 1