首頁 > 後端開發 > C++ > 如何使用 LINQ 表達式樹動態選擇具有多個屬性的匿名類型?

如何使用 LINQ 表達式樹動態選擇具有多個屬性的匿名類型?

Linda Hamilton
發布: 2025-01-22 19:01:11
原創
975 人瀏覽過

How to Dynamically Select Anonymous Types with Multiple Properties Using LINQ Expression Trees?

利用LINQ表達式樹動態選擇匿名型別

引言

LINQ表達式樹提供了一種強大的機制,用於動態建立和修改查詢。一個常見的需求是選擇具有多個屬性的匿名類型。雖然選擇單一屬性相對簡單,但在select lambda中定義多個屬性可能會帶來挑戰。

使用反射發射的解決方案

為了解決這個問題,我們可以利用反射發射和輔助類別來動態產生匿名類型。以下程式碼示範如何實現這一點:

SelectDynamic方法

<code class="language-csharp">public static IQueryable SelectDynamic(this IQueryable source, IEnumerable<string> fieldNames)
{
    // 创建属性名称和相应属性信息的字典
    Dictionary<string, PropertyInfo> sourceProperties = fieldNames.ToDictionary(name => name, name => source.ElementType.GetProperty(name));

    // 生成动态类型
    Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicType(sourceProperties.Values);

    // 创建表达式树
    ParameterExpression sourceItem = Expression.Parameter(source.ElementType, "t");
    IEnumerable<MemberBinding> bindings = dynamicType.GetFields().Select(p => Expression.Bind(p, Expression.Property(sourceItem, sourceProperties[p.Name]))).OfType<MemberBinding>();

    Expression selector = Expression.Lambda(
        Expression.MemberInit(
            Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)),
            bindings
        ),
        sourceItem
    );

    // 返回带有新select表达式的查询
    return source.Provider.CreateQuery(
        Expression.Call(
            typeof(Queryable),
            "Select",
            new Type[] { source.ElementType, dynamicType },
            Expression.Constant(source),
            selector
        )
    );
}</code>
登入後複製

LinqRuntimeTypeBuilder類別

<code class="language-csharp">public static class LinqRuntimeTypeBuilder
{
    // ...
    public static Type GetDynamicType(IEnumerable<PropertyInfo> fields)
    {
        // ...
        string className = GetTypeKey(fields); //  修改参数类型

        TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable);

        foreach (var field in fields)                    
            typeBuilder.DefineField(field.Name, field.PropertyType, FieldAttributes.Public); // 使用field.Name 和 field.PropertyType

        return typeBuilder.CreateType();
    }
    // ...
}</code>
登入後複製

範例用法

要選擇具有多個屬性的匿名類型,請使用下列語法:

<code class="language-csharp">var v = from c in Countries
        where c.City == "London"
        select new { c.Name, c.Population };</code>
登入後複製

您現在可以像存取任何其他實例一樣存取匿名類型的屬性:

<code class="language-csharp">Console.WriteLine(v.Name);
Console.WriteLine(v.Population);</code>
登入後複製

注意: 以上程式碼片段需要補充 LinqRuntimeTypeBuilder 類別的完整實現,包括 GetTypeKey 和其他可能需要的輔助方法。 完整的實作較為複雜,需要處理各種異常情況和類型檢查。 這只是一個簡化的範例,用於說明核心思想。 在實際應用中,需要根據具體需求進行完善和錯誤處理。 此外,直接使用反射發射來建構動態類型可能會影響效能,應根據實際情況權衡利弊。

以上是如何使用 LINQ 表達式樹動態選擇具有多個屬性的匿名類型?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板