我正在阅读一些关于缓存和记忆化以及如何使用委托和泛型轻松实现它的文章。语法非常简单,实现起来也出奇地容易,但我只是觉得由于重复性,应该可以基于属性生成代码,而不必一遍又一遍地编写相同的管道代码。
假设我们从默认示例开始:
class Foo
{
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
然后记住这个:
// Let's say we have a utility class somewhere with the following extension method:
// public static Func<TResult> Memoize<TResult>(this Func<TResult> f)
class Foo
{
public Func<int,int> Fibonacci = fib;
public Foo()
{
Fibonacci = Fibonacci.Memoize();
}
public int fib(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
我想,一旦找到与 Memoize 扩展方法之一匹配的标记方法,只制作一个吐出此代码的代码生成器不是更简单。因此,我可以添加一个属性,而不是编写这个管道代码:
class Foo
{
[Memoize]
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
老实说,我知道这看起来更像是应该由预处理器转换而不是实际代码生成的编译器糖,但我的问题是:
- 您认为在 ac# 源文件中查找具有给定属性的方法、解析参数类型和返回类型并生成与此指纹匹配的委托的最佳方法是什么
- 在不实际覆盖我的代码的情况下,将其集成到构建过程中的最佳方法是什么。在将源文件传递给编译器之前,是否可以对源文件进行一些预处理?
感谢您的任何想法。
更新:
我已经按照 Shay 的建议研究了 Postsharp 库,它似乎非常适合处理事务管理、跟踪或安全等非时间关键型应用程序的工作。
然而,当在时间紧迫的上下文中使用它时,它被证明比委托慢很多。每次实现对 Fibonacci 示例进行 100 万次迭代会导致运行时间降低 80 倍。(每次调用 0.012ms postsharp vs 0.00015ms delegate)
但老实说,在我打算使用它的上下文中,结果是完全可以接受的。感谢您的回复!
更新2:
显然 Postsharp 的作者正在努力开发2.0 版本,其中包括在生成的代码和编译时间方面的性能改进。