Maison >développement back-end >C++ >Comment sélectionner dynamiquement des types anonymes avec plusieurs propriétés à l'aide des arbres d'expression LINQ ?

Comment sélectionner dynamiquement des types anonymes avec plusieurs propriétés à l'aide des arbres d'expression LINQ ?

Linda Hamilton
Linda Hamiltonoriginal
2025-01-22 19:01:11936parcourir

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

Utilisez l'arborescence d'expressions LINQ pour sélectionner dynamiquement des types anonymes

Présentation

Les arbres d'expression LINQ fournissent un mécanisme puissant pour créer et modifier dynamiquement des requêtes. Un besoin courant consiste à sélectionner un type anonyme avec plusieurs propriétés. Bien que la sélection d'une seule propriété soit relativement simple, la définition de plusieurs propriétés dans un lambda sélectionné peut présenter des défis.

Solution utilisant l'émission réfléchie

Pour résoudre ce problème, nous pouvons utiliser l'émission réfléchissante et des classes auxiliaires pour générer dynamiquement des types anonymes. Le code suivant montre comment y parvenir :

Méthode 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>

Classe 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>

Exemple d'utilisation

Pour sélectionner un type anonyme avec plusieurs propriétés, utilisez la syntaxe suivante :

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

Vous pouvez désormais accéder aux propriétés de types anonymes comme n'importe quelle autre instance :

<code class="language-csharp">Console.WriteLine(v.Name);
Console.WriteLine(v.Population);</code>

Remarque : L'extrait de code ci-dessus doit être complété par une implémentation complète de la classe LinqRuntimeTypeBuilder, y compris GetTypeKey et d'autres méthodes d'assistance qui peuvent être nécessaires. L'implémentation complète est complexe et nécessite la gestion de diverses exceptions et la vérification de type. Ceci est juste un exemple simplifié pour illustrer l’idée principale. Dans l'application réelle, l'amélioration et la gestion des erreurs doivent être effectuées en fonction des besoins spécifiques. De plus, l'utilisation directe de l'émission réfléchie pour créer des types dynamiques peut affecter les performances, et les avantages et les inconvénients doivent être pesés en fonction de la situation réelle.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn