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

Linq to SQL 核心機制:Table<TEntity> 取得流程與抽象工廠模式

     編輯:關於.NET

DataContext.GetTable<TEntity>() 是開發者最常呼叫的方法,其背後涉及強型別初始化、MetaModel 映射、反射建構與快取機制等關鍵環節。

強型別 DataContext 的表格初始化

若 DataContext 子類別定義了 Table<Entity> 欄位,InitTables() 會透過反射自動填充:

private void InitTables(object schema)
{
    foreach (FieldInfo info in schema.GetType().GetFields(
        BindingFlags.Public | BindingFlags.Instance))
    {
        Type fieldType = info.FieldType;
        if (fieldType.IsGenericType &&
            fieldType.GetGenericTypeDefinition() == typeof(Table<>) &&
            ((ITable)info.GetValue(schema)) == null)
        {
            Type entityType = fieldType.GetGenericArguments()[0];
            ITable table = this.GetTable(entityType);
            info.SetValue(schema, table);
        }
    }
}

此機制僅在強型別情境下啟動,預設 DataContext 輕量無此開銷。

GetTable 核心邏輯:映射驗證、反射建構、字典快取

public Table<TEntity> GetTable<TEntity>() where TEntity : class
{
    this.CheckDispose();
    MetaTable metaTable = this.services.Model.GetTable(typeof(TEntity));
    if (metaTable == null)
        throw Error.TypeIsNotMarkedAsTable(typeof(TEntity));

    ITable table = this.GetTable(metaTable);
    if (table.ElementType != typeof(TEntity))
        throw Error.CouldNotGetTableForSubtype(typeof(TEntity), metaTable.RowType.Type);

    return (Table<TEntity>)table;
}

private ITable GetTable(MetaTable metaTable)
{
    ITable table;
    if (!this.tables.TryGetValue(metaTable, out table))
    {
        ValidateTable(metaTable);
        table = (ITable)Activator.CreateInstance(
            typeof(Table<>).MakeGenericType(metaTable.RowType.Type),
            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
            null, new object[] { this, metaTable }, null);
        this.tables.Add(metaTable, table);
    }
    return table;
}

關鍵點解析

  • MetaModel.GetTable:依映射方式 (Attribute/Xml) 回傳對應 MetaTable
  • 私有建構子 + 反射:Table<T> 建構子為私有,且泛型參數執行期才確定,故必須用 Activator.CreateInstance 配合 MakeGenericType 建構
  • 字典快取:Dictionary<MetaTable, ITable> 避免重複反射開銷,形成變體單例模式

抽象工廠模式:MetaModel 作為產品家族工廠

MetaModel 定義 GetTable、GetFunction、GetMetaType 等建構方法:

  • AttributeMetaModel → 建構 AttributeMetaTable、AttributeMetaFunction...
  • MappedMetaModel (Xml) → 建構 MappedMetaTable、MappedMetaFunction...

抽象工廠類別圖

確保同一映射模式下建構的產品屬於同一家族,避免混用 Attribute 與 Xml 映射產品造成不一致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved