You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:45:01