繁体   English   中英

拦截方法调用或带反射的属性更改

[英]Intercept Method Invocation or Property Change with Reflection

我正在尝试创建一个泛型类,无论何时调用方法或访问或更改属性,都会触发事件。 它也可能会响应其他更改或采取的措施触发事件,但就目前而言。

为了做到这一点,我想拦截每个方法调用和每个属性访问/更改,但我无法确切知道我正在处理哪些方法。 没有给定的接口定义将要使用的每个泛型T ,因此必须使用反射。 这是我设想的方式( Trigger<T>是类, genericT类型):

public Trigger()
{
    this.generic = default(T);

    foreach (MethodInfo m in generic.GetType().GetMethods())
    {
        // This is pseudocode, since I can't just set MethodInfo to a new method
        m = delegate()
            {
                m.Invoke(this.generic, null);
                if (MethodCalled != null)
                    MethodCalled(this, eventArgs /*imagine these are valid EventArgs*/);
            };
    }
}

我意识到我已经大大简化了这个问题。 首先,我必须处理参数。 其次,你不能像这样以编程方式覆盖方法。 第三,我什至还没有开始研究房地产。 另外,我必须只为对象改变这些东西,而不是整个类型,所以我不确定它是如何工作的。

我已经完成了我的研究,而且我发现所有内容都令人困惑。 我意识到我在某种程度上应该使用AOP,但我从未做过OOP和程序编程之外的任何事情,所以我宁愿迷失在这个密集的知识丛林中。 这听起来像我需要使用PostSharp或统一,但我仍然不知道以后怎么 所有 ,和 2 ,也是这个 (所有单独的环节,每个字)。

有没有更简单的方法来做到这一点? 我什至可以在不使用接口或预定义类的情况下做到这一点?

这是泛型,使我的问题特别复杂。 如果我可以让一个类继承自T ,然后使用代理来捕获它的方法调用和属性访问/更改,那么事情可能会更简单一些,尽管我仍然缺乏对AOP的基本理解。 您可以提供的任何帮助将不胜感激。 如果可能的话,请在初级阶段写下你的答案(虽然我非常了解我的OOP,就像我说的,我不知道关于AOP的第一件事)。

您可以使用NConcern做到这一点, NConcern是我积极工作的新开源AOP框架。

public class Trigger<T> : Aspect
{
    static public event EventArgs MethodCalled;
    static private Trigger<T> m_Singleton = new Trigger<T>();

    //Auto weaving aspect
    static Trigger()
    {
        Aspect.Weave<Trigger<T>>(method => method.ReflectedType == typeof(T));
    }

    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //define an advice to trigger only when method execution not failed
        yield return Advice.Basic.After.Returning(() => 
        {
            if (MethodCalled != null)
            {
                MethodCalled(this, null);
            }
        });
    }
}

public class A
{
    public void Test()
    {
    }
}

int main(string[] args)
{
    Trigger<A>.MethodCalled += ...
    new A().Test();
}

您可以在此处找到类似的示例代码源: 使用NConcern实现的观察模式示例

NConcern AOP Framework是在运行时工作的轻型框架。 它与代码注入一起工作,通过继承避免了工厂/代理。 它允许您通过在方法之前/之后或周围注入可使用简单委托,ILGenerator或表达式树(linq)创建的代码来向类中添加方面。 它可以处理密封类,密封方法,虚拟方法或显式/隐式接口实现。

在我的示例中,我创建了一个从Aspect派生的类(抽象类)。

当一个类从Aspect派生时,它必须通过返回一个Advice实例(Before / After / After.Returning / After.Throwing或Around)来实现Advise方法。 每个都可以使用Delegate或Expression创建,以定义您在方法拦截时需要执行的操作。

public class MyAspect : IAspect
{
    //this method is called initially (not on interception) to rewrite method body.
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //this block of code means that method will be rewrite to execute a write method name to console before original code only for public methods
        if (method.IsPublic)
        {
            yield return Advice.Basic.Before(() => Console.WriteLine(method.Name));
        }
    }
}

用法

//attach myaspect to A class. All methods of A will be passed to Advise method to process methods rewriting.
Aspect.Weave<MyAspect>(method => method.ReflectedType == typeof(A));

//detach myaspect from A class. All methods will be rewrite to give back original code.
Aspect.Release<MyAspect>(method => method.ReflectedType == typeof(A));

无需诉诸使用后编织IL编织的完整AOP框架,您可以使用Castle的DynamicProxy并创建拦截器。 你可以在网上找到很多教程:

为了使拦截器正常工作,您需要确保通用类的方法和属性是virtual 这允许DynamicProxy的运行时编织代码生成包装您的类的代理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM