我如何拦截在C#中的方法调用? [英] How do I intercept a method call in C#?

查看:453
本文介绍了我如何拦截在C#中的方法调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于一个给定的类我想有跟踪功能,即我想记录每个方法调用(方法签名和实际参数值)和每个方法退出(只是方法签名)。

For a given class I would like to have tracing functionality i.e. I would like to log every method call (method signature and actual parameter values) and every method exit (just the method signature).

我如何做到这一点假设:

How do I accomplish this assuming that:


  • 我不希望使用任何第三方
    AOP库C#,

  • 我不想重复code添加到所有我要跟踪的方法,

  • 我不想改变类的公共API - 类的用户应该能够调用的所有方法中完全相同的方式。

为了使问题更具体,让我们假设有3类:

To make the question more concrete let's assume there are 3 classes:

 public class Caller 
 {
     public static void Call() 
     {
         Traced traced = new Traced();
         traced.Method1();
         traced.Method2(); 
     }
 }

 public class Traced 
 {
     public void Method1(String name, Int32 value) { }

     public void Method2(Object object) { }
 }

 public class Logger
 {
     public static void LogStart(MethodInfo method, Object[] parameterValues);

     public static void LogEnd(MethodInfo method);
 }

我如何调用的 Logger.LogStart 的和的 Logger.LogEnd 的每一个调用的方法1 的和的方法2 的无修改的 Caller.Call 的方法,并没有明确添加调用的 Traced.Method1 的和的 Traced.Method2 的?

How do I invoke Logger.LogStart and Logger.LogEnd for every call to Method1 and Method2 without modifying the Caller.Call method and without adding the calls explicitly to Traced.Method1 and Traced.Method2?

编辑:什么将是解决办法,如果我被允许稍微改变调用方法

What would be the solution if I'm allowed to slightly change the Call method?

推荐答案

C#不是一种面向AOP的语言。它有一些AOP功能和您可以模拟另一些,但使AOP使用C#是痛苦的。

C# is not an AOP oriented language. It has some AOP features and you can emulate some others but making AOP with C# is painful.

我抬头的方法做你想要做什么,我发现没有简单的方法来做到这一点。

I looked up for ways to do exactly what you wanted to do and I found no easy way to do it.

据我了解,这是你想要做什么:

As I understand it, this is what you want to do:

[Log()]
public void Method1(String name, Int32 value);

在为了做到这一点,你有两个主要选项以及

and in order to do that you have two main options


  1. 继承自MarshalByRefObject或ContextBoundObject类,并定义从IMessageSink继承的属性。 本文有一个很好的例子。你必须考虑nontheless,使用一个MarshalByRefObject的性能会下降像地狱,我的意思是,我说的是一个10倍的性能失去了尝试之前仔细考虑。

  1. Inherit your class from MarshalByRefObject or ContextBoundObject and define an attribute which inherits from IMessageSink. This article has a good example. You have to consider nontheless that using a MarshalByRefObject the performance will go down like hell, and I mean it, I'm talking about a 10x performance lost so think carefully before trying that.

另外一种选择是注入code直接。在运行时,这意味着你将不得不使用反射来读每个类,获取其属性和注入此时,相应的调用(为此事我想,因为我认为Reflection.Emit的止跌,你不能使用Reflection.Emit的方法'T允许你插入新的code一个已经存在的方法内)。在设计时,这将意味着创建的扩展,CLR编译器,我有诚实的它是如何做不知道。

The other option is to inject code directly. In runtime, meaning you'll have to use reflection to "read" every class, get its attributes and inject the appropiate call (and for that matter I think you couldn't use the Reflection.Emit method as I think Reflection.Emit wouldn't allow you to insert new code inside an already existing method). At design time this will mean creating an extension to the CLR compiler which I have honestly no idea on how it's done.

最后一个选项是使用 IoC框架。也许这不是完美的解决方案,因为大多数的IoC框架工程通过定义入口点,这允许挂接方法,但是,这取决于你想才达到的东西,这可能是一个公平的aproximation。

The final option is using an IoC framework. Maybe it's not the perfect solution as most IoC frameworks works by defining entry points which allow methods to be hooked but, depending on what you want to achive, that might be a fair aproximation.

这篇关于我如何拦截在C#中的方法调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆