C#中关于AOP的建议

10

我有一个基于 ASP.NET 3.5 SP1 的 Webforms 应用程序,使用 MVP 模式(监管控制器)和 DI(autofac)。我的 Presenter 调用域中定义的仓储契约(DDD),这些契约在基础架构项目中实现。

Presenter 调用的仓储方法可能会出错,因此我需要记录异常并在视图上设置错误消息。

以前,我会向 Presenter 构造函数添加 另一个 参数,将引用存储在基本 Presenter 中,并在 Catch 块中调用 Log 方法。虽然我不太喜欢这种方法,但它可以完成工作。

我可以使用工厂获取日志类(如此描述),但我想先探索 AOP,因为它似乎非常有趣。

我已经阅读了编译时和运行时 AOP 的内容,并且想知道人们对不同解决方案的经验、优点、缺点和建议等。

从我所了解的情况来看,.NET 中有四个主要的 AOP 框架:

  • Castle Windsor - 我通常不使用它,因为它有很多我不需要的功能。
  • Spring.net - 据说表现良好,但通过其 xml 配置让人畏惧(我不喜欢非流畅的配置)。
  • PostSharp - 基于属性驱动(我喜欢这个),但曾经有一些行号问题,不确定是否还存在。
  • Unity - 有很多我实际上不需要的功能。

我看到 另一个问题有一些不错的答案,但已经是一年半以前的内容了。在此期间是否开发了更新、更好的框架,或者对现有解决方案进行了增强需要考虑?

参考意见,我选择了Autofac作为依赖注入的框架,因为它流畅、易于使用,我找不到任何负面评论,而且它只是有效。

有没有关于我应该尝试哪个AOP框架的建议?感谢您阅读了所有内容并提供任何想法。


1
我对您想要使用AOP的详细信息很感兴趣。到目前为止,我还没有找到一个能够满足我的需求的好场景。例如,日志记录。AOP记录器可以告诉我何时调用了特定的方法,但这并不足够。我总是需要在方法内部和周围使用记录器。我很想知道AOP如何帮助您。我并不是在抨击AOP——我只是持怀疑态度,并寻找真正的现实场景来进行AOP编程。 - Kevin Won
我在问题中提到,目前它是用于记录异常。 - blu
回头看,你的观点很有道理。最终我使用了一个工厂和一个委托来创建记录器,并将其映射到我的IoC容器中。在给定的时间范围内,我没有选择走AOP的路线,但我仍然对它的实用性感兴趣。 - blu
一般来说,日志记录经常被用作AOP的一个很好的例子,但这并不完全正确!正如您提到的原因,如果我可以总结一下,那就是“每个需要记录日志的地方都要记录特定的内容”。另一方面,跟踪是AOP的理想应用,因为在这种情况下,建议非常通用,并且在每种情况下都是相同的。然而,话虽如此,异常日志记录可以变得通用,因此我认为在这种情况下,它是AOP的一个很好的候选对象。这只是理论,因为我刚开始学习AOP :-} - Myster
即使使用异常日志记录,AOP 似乎仍然不能很好地工作。大多数情况下,我会在方法中使用 try/catch 并重新包装错误,以便为用户/开发人员提供更具体和更有用的信息。 - Kevin Won
3个回答

4
简短回答来说,为了简单易用,您真的不能错过PostSharp。
更长的回答是:在我看来,你应该根据你想要实现的目标选择两个框架之一。
如果你想要基于上下文改变的方面,请考虑Spring.NET(或任何一个基于配置在运行时注入代码的AOP框架)。这使得您可以根据您正在做的事情自定义对象的行为。例如,通过您的配置,您可以在控制台应用程序中使用一种类型的日志记录,在Web应用程序中使用另一种类型的日志记录。请注意,Spring也是一个DI容器(以及其他几个东西)——它远不止于AOP,并且值得学习如何使用。
另一方面,如果您希望始终生效的行为,而不考虑上下文,则PostSharp(编译时织入)是您最好的选择。这实际上相当于在您应用方面的每个方法中包含代码。
针对您所做的事情,我建议您从PostSharp开始。

感谢您的回答,我将其作为最佳答案接受。 - blu
每位开发者 599 €* PostSharp Ultimate - Legends

1
对于简单的方面场景,我会将方法体作为块传递给处理方面的通用方法,即实现“中间洞”设计模式
例如:
public class Class
{
    public void MethodWithoutAspect()
    {
        var dummy = new string('a', 10);

        Console.WriteLine(dummy);
    }

    public void MethodWithAspect()
    {
        Aspect.LogException(() =>
        {
            var dummy = new string('a', 10);

            Console.WriteLine(dummy);
        });
    }
}

public static class Aspect
{
    public static void LogException(Action block)
    {
        try
        {
           block();
        }
        catch (Exception e)
        {
            Log(e);
            throw;
        }
    }

    private static void Log(Exception e)
    {
        throw new NotImplementedException();
    }
}

请在给出负评时添加评论。 - Martin R-L
1
-1 这种技术与AOP无关。 - George Polevoy
AOP的概念是在不改变现有实现的情况下向现有代码注入行为。在这个示例中,如果您决定更改方面,则必须重构所有代码。 - Diego Mendes

0

我已经使用PostSharp有一段时间了,必须说我喜欢它易用性和实现的简单性。

我还必须补充说,个人而言,当我使用框架时,我总是尝试坚持单一职责框架,除非该框架包含我需要的许多组件或者补充核心功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接