首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

AOP 實戰:延遲載入 LazyLoad 實作原始碼深度解析(上)

     編輯:關於C語言

背景:以 ContextBoundObject 實現 AOP 攔截

本系列展示 FaibClass.Data 框架中兩個 AOP 應用:實體集合更新與延遲載入。核心架構採 Attribute → ContextProperty → MessageSink 鏈,要求實體類別繼承 ContextBoundObject,利用 .NET 訊息傳遞機制攔截方法呼叫。

一、LazyLoadableAttribute:標記可延遲載入的實體


[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

二、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);
    }
}

架構角色

三、ContextBoundObject 前提與效能考量

  • 實體類別必須繼承 ContextBoundObject
  • 每次方法呼叫經過 Proxy → Sink Chain → 實體,有額外開銷
  • 作者實測影響「不大」,暫不採用靜態編織(如 PostSharp)
  • 適用場景:領域模型方法呼叫頻率中等、橫切關注點複雜(延遲載入、變更追蹤、權限、日誌)

四、原始碼結構總覽

FaibClass.Data
├── LazyLoadableAttribute.cs          // 標記屬性
├── Aspect
│   ├── LazyLoadableProperty.cs       // 上下文屬性 + Sink 工廠
│   └── LazyLoadableSink.cs           // 訊息攔截核心(下篇解析)

總結

LazyLoadableAttribute 標記實體類別參與 AOP,透過 IContextAttribute 在物件建構時注入 LazyLoadableProperty,後者實作 IContributeObjectSink 建立 LazyLoadableSink 加入訊息接收器鏈。下一篇將深入解析 LazyLoadableSink.HandleMessage 如何攔截 get_ 方法、判斷導航屬性、觸發資料庫查詢並快取結果。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
角色介面職責
AttributeIContextAttribute, IContextProperty標記類別、參與上下文建構
PropertyIContextProperty, IContributeObjectSink驗證上下文、建立 Sink
SinkIMessageSink攔截訊息、執行橫切邏輯