在C#(serilog)中,如何在通用接口+;是否可以以正确的方式保留父/子关系?

在C#(serilog)中,如何在通用接口+;是否可以以正确的方式保留父/子关系?,c#,serilog,C#,Serilog,我们有现有的服务,其中用于日志记录的接口被注入子构造函数并传递给其父类(基) 现有: Public class Child: Parent public Ctor(ILogger logger) : base(ILogger logger) 新增:(将ILogger修改为IMyLogger,它在内部使用Serilog Logger API进行日志记录) 选项1使用反射,我们永远不能依赖堆栈帧来找到进行日志调用的正确方法。此外,性能也将受到影响 我觉得选项2是一种更简洁的方式,每个子都有

我们有现有的服务,其中用于日志记录的接口被注入子构造函数并传递给其父类(基)

现有:

Public class Child: Parent
    public Ctor(ILogger logger) : base(ILogger logger)
新增:(将ILogger修改为IMyLogger,它在内部使用Serilog Logger API进行日志记录)

选项1使用反射,我们永远不能依赖堆栈帧来找到进行日志调用的正确方法。此外,性能也将受到影响

我觉得选项2是一种更简洁的方式,每个
都有自己的
上下文
日志
可以在单元测试中模拟

伐木工人应该为我感觉到的每项服务各一名。但我很乐意被各种各样的想法和其他更好的方法所冲击,以处理这个设计

福迪阿诺塔尔酒店 我之所以需要引入一个通用记录器,是为了将一个类型绑定到记录器实现,稍后我可以将其用作Serilog源上下文

我已经成功地为Fody使用了
Anotar.Serilog
插件,所以我不必担心这样的细节

你的代码 编译什么
公共类MyClass
{
静态ILogger logger=Log.ForContext();
void MyMethod()
{
if(logger.IsEnabled(LogEventLevel.Debug))
{
记录器
.ForContext(“方法名”,“Void MyMethod()”)
.ForContext(“行号”,8)
.Debug(“TheMessage”);
}
}
}
一个潜在的缺点是,您无法在单元测试中轻松测试类的日志记录行为,因为您没有调用注入的、可模拟的接口。但是这些年来,我尝试了很多不同的方法,而这一种方法有着最大的优点和最少的缺点。此外,我开始觉得日志记录是一个贯穿各领域的问题,它与软件体系结构的常规规则有所不同

使用注入避免泛型 但是如果您真的喜欢使用注入式ILogger,那么应该能够避免注入泛型类型。改为插入非通用的
ILogger
。细节将取决于您的DI框架,但它们几乎都允许您使用一个知道您要注入的类型的工厂来定义注入。您可以将该类型传递到

当然,这意味着当基类发出一条日志消息时,它似乎来自它的子类,这在我看来很奇怪。为了避免这种情况,您可以对日志记录器使用属性注入而不是构造函数注入


或者,您可以通过重新设计类,使其更倾向于组合而不是继承来完全避免这个问题。通常,您可以将父类作为依赖项注入到子类中,并最终获得更好的长期设计模式。

如果我没有弄错,您所需要的只是一个注入工厂,它将在您解决某个日志时创建一个特定的日志记录程序。。。类似的东西。对不起。没有。正如我所写的,现有的代码已经注入了ILogger。但我想给伊洛格注射。但正如在代码的“新”部分中指出的,我不能将ILogger注入到预期“伊洛格。我很困惑,如果我们必须将ILogger注入基地。我觉得每个孩子都应该有自己的记录器,基地也应该有自己的记录器。我强烈推荐阅读。您可以将依赖项减少为
ILogger
。为什么基类有自己的记录器类型,为什么不仅仅是
ILogger
?@ErikPhilips-我将查看您建议的链接。然而,为了回答您的问题,由于我正在通过注入一个新的IMyLogger来重构大量现有服务,所以我希望确保更改最少。为什么我使用ILogger是因为遵循MS的建议,以高效/优雅的方式获取类型上下文。静态工厂方法?伊克斯。@ErikPhilips:你能详细说明一下吗?虽然我通常更喜欢注入,但我发现它的好处大多不适用于伐木工人。你是否曾经因为使用静态工厂方法获取记录器而被咬过?如果使用静态工厂方法,您将无法使用记录器进行的操作?我喜欢听别人的经验。你如何配置静态方法记录器?这也要求每个程序员都知道如何创建日志,这就是为什么DI首先存在的原因,所以人们不需要知道如何以静态的方式创建接口
Log.Logger=loggerConfiguration.CreateLogger()我发现没有必要将不同的日志记录配置注入不同的服务。@ErikPhilips:关于部落知识,我想你没有仔细阅读我的答案。我的实际代码只是说
LogTo.Debug(“一些消息”)
,这不需要比注入
ILogger
更多的部落知识。Fody Weavers神奇地制作了一个记录器,并为我添加了一组上下文信息。
Public class Child: Parent
    public Ctor(IMyLogger<Child> logger) : base(IMyLogger<Parent> logger)
Public class Child: Parent
    public Ctor(ILogger<Child> logger) : base()
public class MyClass
{
    void MyMethod()
    {
        LogTo.Debug("TheMessage");
    }
}

public class MyClass
{
    static ILogger logger = Log.ForContext<MyClass>();

    void MyMethod()
    {
        if (logger.IsEnabled(LogEventLevel.Debug))
        {
            logger
                .ForContext("MethodName", "Void MyMethod()")
                .ForContext("LineNumber", 8)
                .Debug("TheMessage");
        }
    }
}