C#如何在父类中获取子类类型并初始化对应Serilog日志?
解决方案
你尝试用<this>作为泛型参数编译失败的原因是:泛型参数需要编译时确定的类型,而this是运行时实例,无法作为编译时泛型参数传入。以下两种方案可以实现父类统一初始化子类日志上下文的需求:
方案1:基于运行时类型创建日志上下文
直接在父类构造函数中通过this.GetType()获取当前实例的实际子类类型,调用Serilog原生的ForContext(Type)方法创建对应上下文的日志实例,无需泛型:
public abstract class Parent { protected Serilog.ILogger LoggerDefinedInParentClass; public Parent(Serilog.ILogger logger) { // 获取当前实例的运行时类型(即子类类型),创建对应日志上下文 LoggerDefinedInParentClass = logger.ForContext(this.GetType()); } public virtual void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, ParentMethod1"); } public virtual void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, ParentMethod2"); } } public class Child1 : Parent { public Child1(Serilog.ILogger logger) : base(logger) { } public override void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, Child1-1"); } public override void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, Child1-2"); } } public class Child2 : Parent { public Child2(Serilog.ILogger logger) : base(logger) { } public override void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, Child2-1"); } public override void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, Child2-2"); } }
关键说明:
- 移除了自定义的
GetCurrentClassLogger<T>,直接使用Serilog原生方法更简洁 - 修正了原代码中重复定义方法的问题,用
virtual+override实现子类重写 - 日志上下文自动关联到子类类型,输出日志的来源会显示为
Child1或Child2
方案2:泛型基类实现编译时类型绑定
将父类定义为泛型类,子类继承时指定自身作为类型参数,实现编译时类型安全的日志上下文绑定:
public abstract class Parent<T> where T : Parent<T> { protected Serilog.ILogger LoggerDefinedInParentClass; public Parent(Serilog.ILogger logger) { // 用泛型参数T(即子类类型)创建日志上下文 LoggerDefinedInParentClass = logger.ForContext<T>(); } public virtual void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, ParentMethod1"); } public virtual void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, ParentMethod2"); } } public class Child1 : Parent<Child1> { public Child1(Serilog.ILogger logger) : base(logger) { } public override void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, Child1-1"); } public override void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, Child1-2"); } } public class Child2 : Parent<Child2> { public Child2(Serilog.ILogger logger) : base(logger) { } public override void ParentMethod1() { LoggerDefinedInParentClass.Information("Hello, Child2-1"); } public override void ParentMethod2() { LoggerDefinedInParentClass.Information("Hello, Child2-2"); } }
关键说明:
- 泛型约束
where T : Parent<T>确保子类必须传入自身类型 - 编译时即可确定日志上下文类型,无需反射,性能略优
内容的提问来源于stack exchange,提问作者scorpion35
相关产品推荐
相关产品推荐

