使用自定义属性装饰方法

时间:2011-03-09 10:08:36

标签: c# .net attributes decorator

我有一些功能,我想记录它们所消耗的时间。

DBResult LongTask(DBCommand command)
{
   ...
}

有没有办法实现这个

[LogTimeUsed()]
DBResult LongTask(DBCommand command)
{
   ...
}

这样我可以在每次调用此函数时调用class / function,并且可以注入自己的代码,获取命令和DBResult的访问权以及在函数中花费的日志时间吗?

6 个答案:

答案 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

如何将参数传递给前处理器或后处理器需要考虑。