4

有没有办法拦截一些方法调用而不对方法本身进行任何代码更改?

我不需要在运行时注入任何自定义行为,只需将自定义性能日志添加到现有项目。

4

6 回答 6

14

你想要面向方面的编程。

AOP 有 4 种主要风格

  1. 基于运行时RealProxy的 AOP
  2. 运行时子类/虚方法 AOP
  3. 编译后 IL weave AOP
  4. 预编译源代码 AOP

以上按执行速度排序(从最慢到最快)。注意最后两个“应该”是相同的速度。但是,我希望编译器产生比 Post Compile IL weave 更好的 IL。

第一个阵营通常包括 IOC 容器,因为它们非常适合这种模式,包括但不限于

  • 统一
  • 春天.NET
  • 温莎城堡
  • 夏普快递

第二个阵营非常少见,我能想到的唯一项目是 Entity Framework(它用于延迟加载,但它不可扩展,也不能自定义)。

第三个阵营也很少,因为这种技术非常复杂和困难。这可以通过在编译后编辑 dll 程序集来添加所需的额外代码。

  • Postsharp Pro
  • 莫诺·塞西尔
  • Fody(一个 mono.cecil 包装器)

最后的营地相对较新。事实上,如此新,唯一真正的入口是实验性的 MS Roslyn。这实际上是一个 C# 编译器。所以......是的......它很神奇。

现在,如果您在性能关键代码方面遇到真正的巨大性能问题,我建议您使用 Fody。最棒的是它是免费的(与 Postsharp Pro 不同),它使用 nuget 并且 Fody.MethodTimer中已经有一个性能工具

于 2014-08-18T15:15:12.350 回答
3

您可以使用任何 AOP 框架,例如Spring .NETUnity,在方法执行之前或之后拦截调用。因此,您不需要更改方法代码。

于 2014-08-18T14:57:28.137 回答
3

我已经成功地使用了Castle DynamicProxy。它比成熟的 AOP 框架更轻量级,并且可以在没有 IoC 容器的情况下使用。

于 2014-08-18T15:09:09.307 回答
3

您可以查看面向方面的编程,看看它是否适合您的情况。

例如: http ://docs.castleproject.org/Default.aspx?Page=Introduction-to-AOP-With-Castle&NS=Windsor&AspxAutoDetectCookieSupport=1

http://fgheysels.blogspot.be/2006/11/aspect-orienting-programming-in-net.html

于 2014-08-18T14:55:59.830 回答
2

您正在寻找的是 Fody:https ://github.com/fody

它开源、稳定,并且有很多针对不同 AOP 用例的插件。我在一个巨大的商业应用程序中使用它,它运行得很好。安装和配置非常简单,只需几分钟即可通过 nuget 完成。

一些示例插件是:

  • PropertyChanged:(在编译时将 INotifyPropertyChanged 代码注入属性)
  • Anotar(通过静态类和一些 IL 操作简化日志记录)
  • Method Timer(注入一些非常基本的方法计时代码)
  • ... 还有很多!

要求、示例和文档可以在 fodys github 页面上找到。

于 2014-08-18T15:07:35.913 回答
2

使用PostSharp

[Serializable]
public class LogPerformance : OnMethodBoundaryAspect
{
    [NonSerialized]
    Stopwatch _stopWatch;

    public override void OnEntry(MethodExecutionArgs args)
    {
        _stopWatch = Stopwatch.StartNew();
        base.OnEntry(args);
    }

    public override void OnExit(PostSharp.Aspects.MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("[{0}] took {1} ms to execute",
          new StackTrace().GetFrame(1).GetMethod().Name,
            _StopWatch.ElapsedMilliseconds));
        base.OnExit(args);
    }
}

在函数上使用这样的方面:

[LogPerformance]
static void LongRunningCalc()
{
    //Your Code goes here
}

简化自:http://www.codeproject.com/Articles/337564/Aspect-Oriented-Programming-Using-Csharp-and-PostS

于 2014-08-18T15:13:44.450 回答