log4net中读取配置文件的方法有两种,
1、定义程序集级的标签属性,如下:
[assembly: log4net.Config.DOMConfigurator()]
2、调用DOMConfigurator.Configure静态方法
当使用了前一种的方法时,log4net读取配置文件的流程如下:
我们使用静态方法log4net.LogManager.GetLogger返回一个log,
log4net.LogManager.GetLogger的声明如下:
public static ILog GetLogger(Type type)
{
return GetLogger(Assembly.GetCallingAssembly(), type.FullName);
}
跟踪一下可以发现,该方法会调用log4net.spi.DefaultRepositorySelector.ConfigureRepository方法,定义如下
private void ConfigureRepository(Assembly assembly, ILoggerRepository repository)
{
if (assembly == null)
{
throw new ArgumentNullException("assembly");
}
if (repository == null)
{
throw new ArgumentNullException("repository");
}
// Look for the Configurator attributes (eg. DOMConfiguratorAttribute) on the assembly
object[] configAttributes = Attribute.GetCustomAttributes(assembly, typeof(log4net.Config.ConfiguratorAttribute), false);
if (configAttributes != null && configAttributes.Length > 0)
{
// Delegate to the attribute the job of configuring the repository
foreach(log4net.Config.ConfiguratorAttribute configAttr in configAttributes)
{
configAttr.Configure(assembly, repository);
}
}
}
可以看到,log4net.spi.DefaultRepositorySelector.ConfigureRepository反射检查宿主程序集是否定义了DOMConfiguratorAttribute类型(注:DOMConfiguratorAttribute继承了ConfiguratorAttribute)的标签属性,假如找到则调用标签的Configure方法,看看代码发现,标签的Configure方法调用了DOMConfigurator.Configure()方法,如此完成读取配置文件的工作
public sealed class log4net.Config.DOMConfiguratorAttribute : ConfiguratorAttribute
override public void Configure(Assembly assembly, ILoggerRepository repository)
{
...
...
...
if (m_configureAndWatch)
{
DOMConfigurator.ConfigureAndWatch(repository as Hierarchy, new FileInfo(fullPath2ConfigFile));
}
else
{
DOMConfigurator.Configure(repository as Hierarchy, new FileInfo(fullPath2ConfigFile));
}
}
总结:
在宿主程序集中定义Assembly level的标签属性,然后由框架的初始化代码通过反射机制检查宿主程序集,如果找到则使用标签属性完成配置文件的加载工作。在自定义开发.net框架中,我们完全可以使用类似log4net的做法