我试图通过动态代理提出一种方法(静态或实例)方法调用拦截。我希望将其实现为c#扩展方法,但坚持如何为静态方法生成动态代理。
一些用法:
Repository.GetAll<T>().CacheForMinutes(10);
Repository.GetAll<T>().LogWhenErrorOccurs();
//or
var repo = new Repository();
repo.GetAll<T>().CacheForMinutes(10);
repo.GetAll<T>().LogWhenErrorOccurs();
我对任何图书馆(linfu,castle.dynamic proxy 2等)开放。
谢谢!
答案 0 :(得分:9)
完全不可能。
实际上,代理甚至无法在所有实例方法上生成 - 它们必须是虚拟的,因此代理生成器可以创建派生类并覆盖它们。
静态方法永远不是虚拟的,因此不能被代理覆盖。
(从技术上讲,非虚拟方法的解决方法是从MarshalByRefObject
派生类,但基于远程处理的解决方案很慢且很笨重,但仍然不支持静态方法。)
鉴于您的类名为Repository
,我建议您改为使用这些方法实例方法。这些类型的操作通常不应该static
开始。如果你制作它们static
,你会失去很多东西:松耦合,模拟,依赖注入,一定数量的单元可测试性,以及 - 正如你刚刚发现的那样 - 代理和拦截。
答案 1 :(得分:0)
不可能采用常见的拦截策略。
但是大多数在编译时工作的AOP框架都可以做到。 (例如:PostSharp)
我在开源NConcern AOP Framework上工作。
这是一个简单的.NET AOP框架,允许通过交换方法在运行时进行拦截。
它可以完成虚拟方法,非虚方法和静态方法的工作,而无需任何工厂模式和继承需求。
我的建议是避免使用AOP来对抗猴子补丁&#34;和静态方法必须只是&#34;单例用法快捷方式&#34;而不是主流。
在你的情况下,使用单例模式和静态方法作为shortcup和DI(依赖注入)更容易实现简单的代理模式。
示例:
接口
public interface IRepository
{
IQueryable<T> Query<T>()
where T : class;
}
糖使用DI(通过工厂)
static public class Repository
{
//You can wrap the interface (proxy) here if you need...
static private readonly IRepository m_Repository = MyDIFactory.Import<IRepository>();
static public IQueryable<T> Query<T>()
where T : class
{
return Repository.m_Repository.Query<T>();
}
}
用法
Repository.Query<T>().CacheForMinutes(10);
Repository.Query<T>().LogWhenErrorOccurs();