.NET 6 WCF中含Lazy静态方法的NLog日志类继承复用方案
解决方案
问题根源在于静态方法属于定义它的基类,当派生类继承基类后,调用的BuildLogFactory仍然是基类的静态方法,Assembly.GetExecutingAssembly()自然返回基类所在程序集的路径,无法获取派生类的程序集信息。
推荐采用泛型基类的方式实现代码复用,同时确保每个派生类能加载自身程序集路径下的对应配置文件:
1. 定义泛型基类
这个基类利用泛型参数的类型信息,自动获取派生类的程序集路径和类名,生成对应的配置文件路径:
using System.Reflection; using System.IO; using NLog; public abstract class LoggerServiceBase<T> where T : class { public static LogFactory Instance => _instance.Value; private static readonly Lazy<LogFactory> _instance = new Lazy<LogFactory>(BuildLogFactory); private static LogFactory BuildLogFactory() { // 获取派生类的类型信息 var derivedType = typeof(T); // 拿到派生类所在程序集的目录 string basePath = Path.GetDirectoryName(derivedType.Assembly.Location); // 自动生成配置文件名:派生类类名 + .nlog string configFileName = $"{derivedType.Name}.nlog"; string configFilePath = Path.Combine(basePath, configFileName); var logFactory = new LogFactory(); logFactory.Configuration = new XmlLoggingConfiguration(configFilePath, logFactory); return logFactory; } }
2. 实现派生类
每个类库的日志服务类只需要继承上述泛型基类,并将自身类型作为泛型参数传入即可,无需额外编写重复代码:
public class SomeDerivedClassLoggerService : LoggerServiceBase<SomeDerivedClassLoggerService> { } public class SomeClassLoggerService : LoggerServiceBase<SomeClassLoggerService> { }
3. 使用方式
和你原来的调用方式完全一致,无需改动:
static NLog.ILogger _Logger = SomeDerivedClassLoggerService.Instance.GetCurrentClassLogger();
原理说明
泛型基类的静态成员会为每个不同的泛型参数(即每个派生类)创建独立的实例,通过typeof(T)可以准确获取到派生类的类型,进而拿到其所在程序集的路径,同时自动生成与类名匹配的配置文件名,完美解决重复代码和配置文件加载的问题。
内容的提问来源于stack exchange,提问作者FDB
相关产品推荐
相关产品推荐

