本框架實作兩個經典 AOP 場景:
共同架構:Attribute → ContextProperty → MessageSink,基於 ContextBoundObject 訊息傳遞機制。
傳統做法:每個屬性 set 手動呼叫 AddUpdateColumn("PropertyName"),侵入性強、易遺漏、維護困難。
AOP 方案:在類別加上 [EntityListUpdatable],自動攔截所有 set_ 呼叫,比較新舊值,異動時自動記錄。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class EntityListUpdatableAttribute : Attribute, IContextAttribute, IContextProperty
{
internal static string PropertyName = "EntityListUpdatable";
public EntityListUpdatableAttribute() { }
string IContextProperty.Name => PropertyName;
void IContextProperty.Freeze(Context newContext) { }
bool IContextProperty.IsNewContextOK(Context newCtx) => true;
void IContextAttribute.GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new EntityListUpdatableProperty());
}
bool IContextAttribute.IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
{
return ctx.GetProperty(PropertyName) != null;
}
}
| 介面 | 方法 | 用途 |
|---|---|---|
| IContextAttribute | GetPropertiesForNewContext | 物件建構時,向新上下文添加對應 Property |
| IsContextOK | 驗證現有上下文是否已包含必要 Property | |
| IContextProperty | Name | 屬性識別名稱 |
| Freeze | 上下文凍結時回調(通常空實作) | |
| IsNewContextOK | 新上下文是否相容(檢查同名 Property 存在且型別正確) |
MarshalByRefObject:跨上下文邊界以 Proxy 參考ContextBoundObject:繼承自 MarshalByRefObject,啟用上下文屬性IMessageSink:訊息接收器鏈節點,SyncProcessMessage 同步處理IMethodCallMessage:方法呼叫訊息,含 MethodName、InArgsIMethodReturnMessage:方法返回訊息,含 ReturnValue、OutArgs、Exception
FaibClass.Data
├── EntityListUpdatableAttribute.cs
└── Aspect
├── EntityListUpdatableProperty.cs
└── EntityListUpdatableSink.cs
EntityListUpdatableAttribute 實作 IContextAttribute 與 IContextProperty,在物件建構階段向上下文註冊 EntityListUpdatableProperty,後者實作 IContributeObjectSink 提供 EntityListUpdatableSink。Sink 在 HandleMessage 中攔截 set_ 訊息,透過反射取得新舊值比較,異動時呼叫內部 AddUpdateColumn 記錄。下一篇將詳細解析 Sink 核心邏輯與效能考量。