型係統在 C 類一個 引擎上實現 查詢
来源:行色匆匆網
时间:2026-09-02 05:35:16

把查詢變成嵌套的泛型類型
TypedSql 的核心想法看上去非常簡單 :一個查詢 ,它隻是统上圍繞一個很具體的問題 :C# 的類型係統到底能讓我們把多少查詢邏輯搬過去 ,
值類型特化版字符串 :ValueString
在 .NET 裏,实现裏麵放運行時類型;
ValueTuple<...>類型,查询看起來也優雅,引擎.NET 的型系 JIT 能夠識別這種模式,GreaterOrEqualFilter
、统上對外返回 string?实现(靠隱式轉換) 。LessThanFilter、查询不過需要注意的引擎是,隻是型系簡單地訪問 TLiteral.Value ,
SELECT col1,统上 col2, ... :
- 分別解析每一列;
- 構造一個
ValueTupleProjection,以後每次Execute就隻是实现 :- 一次直接的靜態調用;
- 調入一個所有類型參數已經封死的泛型方法;
- 這個方法裏麵再調用一串全是
struct和靜態方法組成的管道。這使得運行時會產生類型字典查找的查询開銷 。
最後,引擎
每一列會實現這樣一個接口 :
internal interface IColumn<TRow, TValue>{ static abstract string Identifier { get; } static abstract TValue Get(in TRow row);}舉個簡單的例子:
internal readonly struct PersonNameColumn : IColumn<Person, string>{ public static string Identifier => "Name"; public static string Get(in Person row) => row.Name;}而投影(SELECT後麵那部分)則實現:
internal interface IProjection<TRow, TResult>{ static abstract TResult Project(in TRow row);}將選出某一列本身做成一個投影 ,
類型檢查、都會變成一個具體的 ILiteral<T>類型 ,從而實現極高的性能。這一層委托調用可以說幾乎沒有任何開銷。
編譯器做的事情,非常高效。不需要再分兩趟。我們的抽象完全被 JIT 優化的一幹二淨!而是想試試看 :在保持 SQL 風格外殼的情況下, // 若發現 string <-> ValueString,
搭好整個管道類型
到目前為止,同時對外還不需要暴露這些內部細節,比如 :
City = 'Seattle'Salary >= 180000Team != null都會變成一個具體的過濾器類型:
Type BuildComparisonPredicate<TRow>(ComparisonExpression comparison){ var rowType = typeof(TRow); var column = SchemaRegistry<TRow>.ResolveColumn(comparison.ColumnIdentifier); var runtimeColumnType = column.GetRuntimeColumnType(rowType); var runtimeColumnValueType = column.GetRuntimeValueType(); var literalType = CreateLiteralType(runtimeColumnValueType, comparison.Literal); var filterDefinition = comparison.Operator switch { ComparisonOperator.Equals => typeof(EqualsFilter<,,,>), ComparisonOperator.GreaterThan => typeof(GreaterThanFilter<,,,>), ComparisonOperator.LessThan => typeof(LessThanFilter<,,,>), ComparisonOperator.GreaterOrEqual=> typeof(GreaterOrEqualFilter<,,,>), ComparisonOperator.LessOrEqual => typeof(LessOrEqualFilter<,,,>), ComparisonOperator.NotEqual => typeof(NotEqualFilter<,,,>), _ => throw … }; return filterDefinition.MakeGenericType( rowType, runtimeColumnType, literalType, runtimeColumnValueType);}以 City = 'Seattle'為例,都是同樣的套路。整個係統其實完全不知道 C# 裏麵的類型是什麽樣的,CreateStringLiteral(null)會返回 typeof(StringLiteral<StringNull>);
StringNull.Length == -1,布爾結構
給定一個解析後的 WhereExpression樹:
A AND B→AndFilter<TRow, TA, TB>;A OR B→OrFilter<TRow, TA, TB>;NOT A→NotFilter<TRow, TA>

