我有一些功能,我想记录它们所消耗的时间。
DBResult LongTask(DBCommand command)
{
...
}
有没有办法实现这个
[LogTimeUsed()]
DBResult LongTask(DBCommand command)
{
...
}
这样我可以在每次调用此函数时调用class / function,并且可以注入自己的代码,获取命令和DBResult的访问权以及在函数中花费的日志时间吗?
答案 0 :(得分:4)
在.NET中没有内置的方法。
如果你希望不使用任何第三方库(正如你在其中一条评论中所说的那样),那么进行代码编织或动态代理生成是很多工作。在这种情况下,最好不要使用属性并使用装饰器设计模式。这是一个例子:
// Define an interface for the operation
public interface IMyLongRunningTask
{
DBResult longTask(DBCommand command);
}
// Define an implementation for the operation:
public class MyLongRunningTask : IMyLongRunningTask
{
public DBResult longTask(DBCommand command)
{
// code here
}
}
现在你可以为IMyLongRunningTask写一个装饰器:
public class MyLongRunningTaskMonitor : IMyLongRunningTask
{
private readonly IMyLongRunningTask wrappedService;
private readonly ILogger logger;
public MyLongRunningTaskMonitor(IMyLongRunningTask wrapped,
ILogger logger)
{
this.wrappedService = wrapped;
this.logger = logger;
}
public DBResult longTask(DBCommand command)
{
var watch = Stopwatch.CreateNew();
var result = this.wrappedService.longTask(command);
this.logger.Log("longTask executed in " +
watch.ElapsedMilliseconds + " ms.");
return result;
}
}
使用依赖项注入时,可以轻松配置在请求MyLongRunningTaskMonitor
时返回的IMyLongRunningTask
。例如:
container.Register<IMyLongRunningTask>(() =>
new MyLongRunningTaskMonitor(
container.GetInstance<MyLongRunningTask>(),
container.GetInstance<ILogger>()
)
);
答案 1 :(得分:2)
您可以使用Castle DynamicProxy。
DynamicProxy为其生成代理 您可以使用的对象 透明地添加或改变行为 他们,提供前/后处理和 许多其他事情。
答案 2 :(得分:0)
如果您自己没有处理该特定类型的属性,则应使用类似PostSharp
之类的内容来研究面向方面编程答案 3 :(得分:0)
您可以使用PostSharp
执行此操作同时检查我的问题答案 - Aspect Oriented Logging with Unity\T4\anything else
答案 4 :(得分:0)
只是添加到第三方的东西列表中有spring AOP(Spring是一个庞大且流行的框架,已经从Java移植到.net)
http://www.springframework.net/doc-latest/reference/html/aop.html
答案 5 :(得分:0)
问题是寻找一种通过使用c#属性在c#中创建装饰器的方法,尝试创建如python中所见的装饰器语法(非常好...... C#社区注意)
通过嵌入&#39;属性可以实现类似的功能。在您的方法名称(例如LongTask_LogTimeUsed)中,然后在LongTask方法中有少量(样板文件)代码读取其方法名称,将前处理或后处理委托给适当的处理程序:
How to get the name of the current method from code
如何将参数传递给前处理器或后处理器需要考虑。