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

时间:2016-03-13 04:55:18

标签: c# .net oop generics aop

我试图创建一个泛型类,只要调用方法或访问或更改属性,就会触发事件。它也可能会针对正在采取的其他变化或行动触发事件,但就目前而言,它就是它。

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

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或Unity,但我仍然不清楚looking at all thisthis之后的情况,these two,以及this(所有单独的链接,每个字)。

有没有更简单的方法呢?我甚至可以在不使用接口或预定义类的情况下完成它吗?

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

2 个答案:

答案 0 :(得分:0)

你可以使用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();
}

您可以在此处找到类似的示例代码来源:Example of observation pattern implemented with 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));

答案 1 :(得分:0)

如果不使用使用post-bulid IL编织的全面AOP框架,您可以使用Castle DynamicProxy并创建拦截器。你可以在网上找到很多教程:

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