如何在调用方法时启动的方法上添加属性?
问题描述:
我有一个相当标准的.net core 2 WebApi项目。我想在一个方法中添加一个属性,该方法将在调用操作时启动。如何在调用方法时启动的方法上添加属性?
在下面的伪代码中,当有人发布到foo
动作时,我想记录POST的正文。为此,我添加了[LogBody]
属性。但我不知道如何实际启动属性中的某个方法。
class SomeController: Controller {
[HttpPost]
[LogBody]
public void foo([FromBody] SomeObj obj) {
return View(obj);
}
}
class LogBodyAttribute: Attribute {
void LogIt() {
string methodName = getMethodName();
string body = new StreamReader(Request.Body, Encoding.UTF8).ReadToEnd();
SaveData(methodName, body);
}
}
P.S.我知道我可以用PostSharp来做到这一点,但我宁愿不要。
答
这些属性提供了包含在编译代码中的静态元数据。这些信息可以在运行时查询并用于执行逻辑;然而,属性本身不能触发一个动作。
给定一个对象,你可以得到的属性是这样的:
Type type = controller.GetType();
var myAttribute = type
.GetMethod(methodName)
.GetCustomAttributes(true)
.OfType<MyAttribute>()
.FirstOrDefault();
布尔参数GetCustomAttributes
表示继承属性是否必须退回。
也许你在找什么是Aspect-oriented programming AOP。这允许您在后编译过程中将代码注入方法和属性。属性可用于包含或排除方法。有不同的AOP产品可用于C#。
另一种方法是使用Decorator pattern。装饰器是一个包装类,它提供了与包装类相同的API,并允许将行为添加到wrappee的方法和属性中。与inversion of control(IoC)容器或Factory method pattern一起使用时,可以自动注入行为。
答
它可以完成,但这并不容易 - 你的问题的直接答案涉及反射和代码注入的东西。这是一个SO问题,可能会帮助你做你想做的事:C# Attribute to trigger an event on invoking a method
你不能真的'启动'一个属性。一个属性只是描述某些东西的元信息。我最好的猜测是插入一些中间件或者一个过滤器来抓取ActionContext,并根据它进行日志记录。 PostSharp的工作原理是在编译时根据属性中提供的元信息在代码中逐字添加代码。 – Jonesopolis