[英]Intercept Method Invocation or Property Change with Reflection
我正在嘗試創建一個泛型類,無論何時調用方法或訪問或更改屬性,都會觸發事件。 它也可能會響應其他更改或采取的措施觸發事件,但就目前而言。
為了做到這一點,我想攔截每個方法調用和每個屬性訪問/更改,但我無法確切知道我正在處理哪些方法。 沒有給定的接口定義將要使用的每個泛型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或統一,但我仍然不知道以后怎么找 在 所有 這 ,和這和這 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.