簡體   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