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 ?
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!