【问题标题】:Adding LogService to my Application将 LogService 添加到我的应用程序
【发布时间】:2012-05-09 15:49:52
【问题描述】:

我有一个应用程序(旧代码)

包含接口Icomponentsave() 方法

以及许多实现它的类。

我想在每次 save() 之后添加日志。

更新

我的设计想法很少:

  • Singelton Logger - 将在每个可记录的操作后调用

我认为LogService 是singelton 的经典案例,但我读到它很难进行单元测试。

  • 装饰器 + 使用 Ioc 初始化的记录器

使用装饰器模式到Icomponent 和额外的log() 方法。

创建从每个装饰器的log() 调用的LogService

  • AOP - 面向方面编程

我读过一点,但不知道。

是否适用于c#?

  • 您对该解决方案有何设计?

更新2

看了代码,发现还有一层接口

在混凝土层之前。我认为我不应该装饰每个特定的界面。对吧?

I_AComponente : IComponente

I_BComponente : IComponente

A : I_AComponente

B : I_BComponente

【问题讨论】:

    标签: c# unit-testing design-patterns .net-3.5 singleton


    【解决方案1】:

    它根本不必是单例的。考虑:

    public void ComponentDecorator : IComponent
    {
        private IComponent component;
        private ILogger logger;
    
        public ComponentDecorator(IComponent component, ILogger logger)
        {
            this.component = component;
            this.logger = logger;
        }
    
        public void Save()
        {
            this.component.Save();
            this.logger.Log("Some important message");
        }
    }
    

    由于无论如何您都会将装饰组件注入到装饰器中,因此也可以注入记录器(这很容易测试)。从单元测试的角度来看,logger 的来源无关紧要。

    此外,您应该检查现有的记录器,而不是滚动您自己的记录器,例如 Apache log4net

    编辑

    单例记录器难以测试的说法可能是因为 C# 中的单例通常会在某处使用 static 字段或静态类来实现。假设你有:

    public static LoggerService
    {
        public static Log(string message) { ... }
    }
    

    现在,在装饰器的方法中,您可能必须按照这些思路做一些事情:

    public void Save()
    {
        this.component.Save();
        LoggerService.Log("Some important message");
    }
    

    这使得测试Save 方法几乎是不可能的,因为您的方法内部具有紧密耦合的依赖关系。如果您可以将LoggerService 配置为不写入文件系统的测试,那就没那么糟糕了(但仍然是解决问题而不是解决问题)。

    inject via interface 中,这个问题自然而然地消失了。 LoggerService 可能仍然是静态类,但它可以简单地提供非静态记录器(并管理它们的生命周期/范围)。这一点也不会使单元测试变得困难。

    【讨论】:

    • 谢谢,但我传递给所有 Icomponent 实现的 ctor 的记录器是单例的。
    • @EladBenda:这根本不重要。由于它是通过接口传递的,因此您可以模拟它(这很重要)。它在测试类之外的外观是无关紧要的。单身不会使其难以测试。我在帖子中添加了解释/示例。
    • might still be static class, but it could simply provide non-static loggers 怎么可能?静态类只有静态字段。我可以做一个静态设置器。
    • @EladBenda:静态类可能有静态方法。您可以从中返回任何您想要的东西(如非静态)。重点是,静态单例类很可能必须管理已创建的记录器的创建和生命周期。
    【解决方案2】:

    是的! AOP 适用于升 C http://www.developerfusion.com/article/5307/aspect-oriented-programming-using-net/

    AOP 是避免在整个代码中编写 Log 语句的好方法。这是您如何在您的应用程序中实现 AOP 的示例....但是,以下链接提供的方法的唯一缺点是您还需要配置 Castle Windsor http://ayende.com/blog/3474/logging-the-aop-way

    【讨论】:

    • 谢谢。在 C# 中使用 AOP 的优缺点是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多