编程语言
首页 > 编程语言> > 首页> C#>如何只使用Castle.DynamicProxy拦截基类方法

首页> C#>如何只使用Castle.DynamicProxy拦截基类方法

作者:互联网

我有2个类,一个用于通过缓存访问数据库和子类.我可以更改两个类的源代码,但是有许多结构不同的类,因此我正在寻找一种方法来生成通用解决方案,以帮助我仅拦截用Attribute标记的方法或其他方法.

这是一个例子

public class BaseClass
{
    [MyAttribute]
    public virtual MyEntity[] GetAll() {}
    [MyAttribute]
    public virtual MyEntity GetByKey(int key) {}
    [MyAttribute]
    public virtual void GetByName(string name) {}
}

public class ChildClass : BaseClass
{
    public override MyEntity GetByKey(int key) 
    {
        if(key > 100)
           return GetCachedEntity(key);
        return base.GetByKey(key);
    }
}

public class MyInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Here I can check any required conditions to decide on the way of processing
        var myCondition = invocation.Method.GetCustomAttributes(false).Any(a => a is MyAttribute);
        if(myCondition)
        {
            // extra logic for marked methods
        }

        invocation.Proceed();
    }
}

public static class MyProxyFactory
{
    private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();

    // here is my generic proxy factory which I want to use for creating proxies for ChildClass objects and another objects that contains similar logic
    public static TInterface CreateProxy<TInterface>(TInterface concreteObject)
        where TInterface : class
    {
        var proxy = proxyGenerator.CreateInterfaceProxyWithTarget(concreteObject, ProxyGenerationOptions.Default, new MyInterceptor());
        return proxy;
    }
}

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class MyAttribute : Attribute {}

我正在尝试对myCondition使用invocation.Method.GetCustomAttributes()并仅标记基类方法,但是问题是,当ChildClass.GetByKey()调用基类方法时,它不会被MyInterceptor.Intercept()方法拦截.

在此示例中,我可以将分解替换为继承,但随后需要在ChildClass中实现GetAll和GetByName方法,并且此解决方案将不是通用的.

如何更改ProxyGenerator设置或CreateProxy()方法来解决我的问题?

var realObject = new ChildClass();
var proxyObject = MyProxyFactory.CreateProxy(realObject);

// extra logic should be executed
proxyObject.GetAll();

// extra logic should be executed
proxyObject.GetByKey(99);

// extra logic should not be executed
proxyObject.GetByKey(101);

解决方法:

一个base.Method调用故意不尝试查找比该类的基类更进一步继承关系的方法重载.代理不会执行幻想,它会覆盖子类中的方法,并依赖于虚拟调用来到达代理而不是其基本实现.或者,如果它是包装代理,则仅拦截外部呼叫-我不知道您使用的代理类型的详细信息.

因此,基本上,一旦编写base.Method,就不会期望发生任何子类魔术.如果需要在层次结构内部的子父交互中进行拦截,则需要重新访问设计方法.

标签:system-reflection,castle-dynamicproxy,c
来源: https://codeday.me/bug/20191110/2013410.html