本系列展示 FaibClass.Data 框架中兩個 AOP 應用:實體集合更新與延遲載入。核心架構採 Attribute → ContextProperty → MessageSink 鏈,要求實體類別繼承 ContextBoundObject,利用 .NET 訊息傳遞機制攔截方法呼叫。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class LazyLoadableAttribute : Attribute, IContextAttribute, IContextProperty
{
internal static string PropertyName = "LazyLoadable";
public LazyLoadableAttribute() { }
// IContextProperty
string IContextProperty.Name => PropertyName;
void IContextProperty.Freeze(Context newContext) { }
bool IContextProperty.IsNewContextOK(Context newCtx) => true;
// IContextAttribute
void IContextAttribute.GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
{
ctorMsg.ContextProperties.Add(new LazyLoadableProperty());
}
bool IContextAttribute.IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
{
return ctx.GetProperty(PropertyName) != null;
}
}
IContextAttribute 參與物件建構期上下文建立IContextProperty 代表上下文屬性,供 Runtime 檢查GetPropertiesForNewContext 注入對應的 LazyLoadableProperty
internal class LazyLoadableProperty : IContextProperty, IContributeObjectSink
{
void IContextProperty.Freeze(Context newContext) { }
string IContextProperty.Name => LazyLoadableAttribute.PropertyName;
bool IContextProperty.IsNewContextOK(Context newCtx)
{
return newCtx.GetProperty(LazyLoadableAttribute.PropertyName) is LazyLoadableProperty;
}
// 核心:建立訊息接收器鏈
IMessageSink IContributeObjectSink.GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
return new LazyLoadableSink(obj, nextSink);
}
}
| 角色 | 介面 | 職責 |
|---|---|---|
| Attribute | IContextAttribute, IContextProperty | 標記類別、參與上下文建構 |
| Property | IContextProperty, IContributeObjectSink | 驗證上下文、建立 Sink |
| Sink | IMessageSink | 攔截訊息、執行橫切邏輯 |