ASP.NET:如何让 AOP/Cross-cutting 关注点的数据可见?

ASP.NET: How to make data visible for AOP/Cross-cutting concerns?

我有兴趣查看与此相关的模式,但这是我眼前的具体问题。

我有一个 要求 修改 Web 应用程序中的日志记录,以便日志中的每个条目都用负责执行代码的实体(用户名或进程名)进行注释这导致了日志条目。例如,而不是:

timestamp level loggerName 一个敏感的 object 已从数据库中删除

你会得到

timestamp level loggerName [ELLIOT.ALDERSON] 一个敏感的object 已从数据库中删除

timestamp level loggerName [DAILY CRON JOB] 敏感 object已从数据库中删除

除了识别执行操作的“用户”(或进程)之外,如果是用户,还有一个要求记录有关请求本身的信息(例如 IP 地址、用户代理、headers 等),尽管这些数据可以写入辅助日志,因此主日志本身保持可读。

在 Java 中,无需修改记录器的接口 就可以轻松做到这一点,因为我们的 HTTP 服务器使用 (Tomcat) 'guarantees' 一个 request/one 线程,使我能够将用户信息和请求信息都放入 thread-local 变量中。我的任何代码,在任何地方,都可以通过询问当前用户和与该线程关联的请求来找出“谁”调用它并访问请求属性,而无需在整个应用程序的每个方法中传递用户和请求变量。这意味着当我的任何代码写入日志时,我的 minimally-modified 记录器代码可以产生所需的输出,而无需更改我的应用程序中对记录器的任何单个调用。

在 C#.NET 中,我不知道该怎么做。 IIS 几乎可以保证从池中重用线程,因此有 thread-local 变量来标识与任何特定方法调用相关联的用户和请求(因此 user/request 绑定到记录器调用那个方法)。我读过的所有 AOP 文章都涉及应用 behavior,而不是 data。当然,在控制器方法本身内部,我可以看到 session 和请求信息。但是控制器调用调用方法的方法调用方法等令人作呕,这些方法没有可见性,除非 session 和请求作为附加参数传递给每个方法,这是一个 non-starter (我还想到并放弃了将堆栈向上移动到控制器,或者直到我确信没有控制器为止;但是,堆栈跟踪本质上只是识别与特定框架关联的源代码,它不会让您访问堆栈上的实际 objects。另外,尽管格式化和写入日志数据很昂贵,但遍历堆栈的额外费用似乎有点过高)。

有没有一种技术可以让我对任意 context-specific 数据(在本例中为 session 并请求 objects)对我的 cross-cutting关注码?

如果您需要静态访问当前请求数据,您可以使用 HttpContext.Current.Items。它是字符串、对象的字典,每个请求都不同。如果您更改线程(即您正在使用异步等待),上下文将被保留,您将找到正确的数据。