无论如何从属性中提取或保存数据?

时间:2011-03-17 17:45:53

标签: c# aop custom-attributes postsharp

我开始使用属性,对于此示例,代码是使用PostSharp 2.0编写的。

我想要做的是具有Stopwatch属性或调用方法可以访问经过时间的方法。

我目前正在使用C#4.0编写此代码

示例属性代码:

[Serializable]
public class StopwatchAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        // Create new stopwatch
        Stopwatch stopwatch = new Stopwatch();

        // Begin timing
        stopwatch.Start();

        args.MethodExecutionTag = stopwatch;
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Stopwatch stopwatch = (Stopwatch)args.MethodExecutionTag;

        // Stop timing
        stopwatch.Stop();

        // Write result
        Debug.WriteLine("Time elapsed: {0} ms", stopwatch.Elapsed);
    }
}

使用属性

[Stopwatch]
public string Search(string LineNo)
{
    // Search for something
    // Is it possible to know how long (from Stopwatch attribute) Search took 
}

public void CallSearch
{
    string x =  Search("xyz");
    // Is it possible to know how long (from Stopwatch attribute) Search took 
}

我得到了经过时间的输出。

但是,无论如何都要扩展这个以便我可以发送经过的时间。

理想情况下,我希望看到SearchCallSearch获取了多长时间,但如果我甚至可以在Search中获得结果然后以某种方式返回它,那就没问题。< / p>

作为一种解决方法,我目前正在使用"Hole in the Middle"模式。

谢谢

4 个答案:

答案 0 :(得分:1)

我认为属性是只读的,并且在编译时完全确定。编译代码后,您无法影响属性。也许你可以保留一个静态的Dictionary(将delegates或MemberInfo映射到执行时间值)来跟踪标记为跟踪其执行时间的每个方法的最后执行时间?

答案 1 :(得分:1)

嗯,在方法结束后,属性中的变量将不复存在。为此,您需要评估数据的日志或其他持久性源。您可以将数据写入静态List或类似的东西,但是没有可以编写的代码,它们将反射性地检查属性本身,以确定具有该属性的方法的最后一次运行所花费的时间(除非属性类具有检查相同的持久存储。)

正如您所写的那样,该属性只是CLR以特殊方式使用的类;它检查是否存在面向方面的属性,根据需要实例化任何属性,并根据需要调用任何处理程序。该类只在运行时需要它的范围内,一旦它不是,它就是GCed。要使用面向方面目的范围之外的属性,可以使用其类型,和/或使用Activator创建它的新实例。

一件事;属性可以具有静态属性。因此,您可以定义静态秒表实例,并将其设置为最近在OnExit中停止的秒表。这将允许您静态地确定用属性修饰的最后一个执行方法的时间。

答案 2 :(得分:0)

可能的解决方案(对不起,我没有测试它,但想法必须明确):

[Serializable]
public class StopwatchAttribute : OnMethodBoundaryAspect
{
    [ThreadStatic]
    private static Stopwatch stopwatch = null;

    public override void OnEntry(MethodExecutionArgs args)
    {
        var sw = stopwatch ?? new Stopwatch();
        args.MethodExecutionTag = sw; // Better to move this line before .Start
        sw.Start();
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        var sw = (Stopwatch) args.MethodExecutionTag;
        sw.Stop();
        Debug.WriteLine("Time elapsed: {0} ms", sw.Elapsed);
    }

    public static Stopwatch Measure(Action action)
    {
        var oldStopwatch = stopwatch;
        stopwatch = new Stopwatch();
        try {
            // !!! Btw, you can measure everything right here.
            action.Invoke();
            return stopwatch;
        }
        finally {
            stopwatch = oldStopwatch;
        }
    }
}

隐含用法:

[Stopwatch]
public string Search(string LineNo)
{
    // Search for something
    // Is it possible to know how long (from Stopwatch attribute) Search took 
}

public void CallSearch
{
    var stopwatch = StopwatchAttribute.Measure(() => {
        string x =  Search("xyz");
    });
    Console.WriteLine("Time elapsed: {0} ms", stopwatch.Elapsed);
}

如您所见,PostSharp的使用似乎不太必要。它可用于记录此类计时,但您必须使用类似方法或您自己的日志访问API来获取记录时间。

答案 3 :(得分:0)

属性应仅用于在设计时向类,属性和方法添加描述,然后可以在运行时通过反射进行检查。

我不会用它来存储业务逻辑。

以下是great article供您参考。