拦截方法调用

Posted

技术标签:

【中文标题】拦截方法调用【英文标题】:Intercept method calls 【发布时间】:2014-10-11 12:57:27 【问题描述】:

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

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

【问题讨论】:

你试过Unity拦截吗? Rosyln 可以-roslyn.codeplex.com/discussions/541688 面向方面的编程可能会对您有所帮助 【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

你要找的是Fody:https://github.com/fody

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

一些示例插件是:

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

使用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

【讨论】:

Postsharp 不是免费的:/ @Only a Curious Mind :我知道,但这是否是对所提出问题的完全有效答案投反对票的理由? 你是对的。对不起。我现在无法删除反对票:( Postsharp 有一个免费的速成版。实际上,此处发布的示例适用于免费版。 +1 postsharp 改变了他们的定价模式,将免费版本锁定为每个项目 10 个课程。【参考方案6】:

你想要面向方面的编程。

AOP 有 4 种主要风格

    基于运行时 RealProxy 的 AOP 运行时子类/虚拟方法 AOP 编译后 IL weave AOP 预编译源代码 AOP

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

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

团结 Spring.NET 温莎城堡 Postsharp Express

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

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

Postsharp 专业版 Mono.Cecil Fody(一个 mono.cecil 包装器)

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

现在,如果您在性能关键代码方面遇到真正的巨大性能问题,我建议您使用 Fody。很棒的是,它是免费的(与 Postsharp Pro 不同),它使用 nuget 和 there is already a performance tool in Fody.MethodTimer。

【讨论】:

Postsharp 还有一个免费的速成版,根据您的使用情况,这可能就足够了。 非常感谢 Fody 的参考,这正是我想要的,只是一些基本的之前/之后方法计时器。 Fody MethodDecorator 在发布版本中有一个令人讨厌的错误,该错误尚未修复 3 年 (github.com/Fody/MethodDecorator/issues/8)。所以我们不得不从 Fody 转到 Roslyn

以上是关于拦截方法调用的主要内容,如果未能解决你的问题,请参考以下文章

拦截方法调用

是否可以拦截方法调用的参数和进行方法调用的方法:AOP

Spring AOP不拦截从对象内部调用的方法

Spring AOP不拦截从对象内部调用的方法原因

Spring AOP不拦截从对象内部调用的方法原因

Spring AOP不拦截从对象内部调用的方法原因