2
votes

Copie des champs d'une classe dans une liste de dictionnaires à l'aide de LINQ

Toutes nos excuses à l'avance si l'en-tête de la question prête à confusion. J'essaierai d'expliquer avec un exemple, j'espère que ce sera clair.

J'ai une classe comme ci-dessous:

var result = new List<A>();

foreach (var l in inputList)
{
    var r = new A();
    r.myDict.Add("elem1",l.elem1);
    r.myDict.Add("elem1",l.elem1);
    r.myDict.Add("elem1",l.elem1);
    r.myDict.Add("elem1",l.elem1);
    result.Add(r);
}

Je veux créer une liste de classes avec ce qui précède (ex: List) en utilisant une entrée qui serait une autre List du type suivant:

class input
{
   public string elem1;
   public string elem2;
   public string elem2;
   public string elem2;
}
Ex: List<input> inputList;

J'ai accompli la même chose en utilisant une boucle foreach comme ci-dessous. Je veux savoir si je peux accomplir la même chose en utilisant LINQ d'une meilleure manière:

class A
{
    Dictionary<string,string> myDict;
}


4 commentaires

"Voici mon code de tête, je le veux avec LINQ" .. pourquoi? Cela ne fonctionne pas de toute façon ...


Pourquoi Linq? quel est le problème avec ça?


@Rahul, ce n'est pas compilable;)


@Sinatr Cela produira des erreurs de compilation ainsi que des exceptions à l'exécution :)


4 Réponses :


0
votes

Vous pouvez essayer ceci:

inputList
  .Select(i => new A(){myDict = new Dictionary<string, string>{{"elem1", i.elem1},{"elem2", i.elem2},{"elem3", i.elem3},{"elem4", i.elem4}}})
  .ToList();

Cela nécessite que myDict soit un champ public, mais d'après votre question, je pense que oui (ou le code doit être à l'intérieur du class).

De plus, je pense que vous avez des noms de champs incorrects, car ils ne sont pas uniques et un tel code ne se compilerait pas, mais j'ai supposé que les noms devraient être elem1 , elem2 , elem3 , elem4.


0 commentaires

0
votes

Si vous souhaitez avoir du code générique pour n'importe quelle classe, la meilleure façon de résoudre ce problème est d'utiliser ToDictionary méthode et reflexion . Pour récupérer tous les champs publics avec ses valeurs, utilisez le code ci-dessous:

var result = inputList
    .Select(item => new A() { 
                                myDict = item
                                           .GetType() // get item's type declaration
                                           .GetFields(BindingFlags.Instance | BindingFlags.Public)) // get all public non static fileds of item's class
                                           .ToDictionary(f => f.Name, f => f.GetValue(item) // get dictionary with field name as the key and field value as the value
                            })
    .ToList();

Si vous avez besoin de récupérer non seulement des membres publics ou des propriétés au lieu de champs, vous pouvez utiliser d'autres méthodes de type de classe . Vous pouvez également créer un algorithme plus générique et récupérer uniquement les champs nécessaires en utilisant des attributions spéciales à ses champs et Méthode GetCustomAttributes .

Notez que le champ myDict doit être public.

p>


3 commentaires

merci, mais qu'est-ce que "r" qui est passé à GetValue ci-dessus?


@vinit TY pour commenter c'est un problème de refactoring :) J'ai mis à jour ma réponse.


Étant donné que vous faites cela pour une liste d'objets, je suggérerais de créer une List à partir de inputList.GetFirst (). GetType () une fois, et de l'utiliser dans le Sélectionnez .



0
votes

Facile à faire avec linq,

input ip = new input();
Dictionary<string, string> myDictionary = typeof(input).GetFields(BindingFlags.Instance | BindingFlags.Public).ToDictionary(x => x.Name, x => x.GetValue(ip).ToString());


0 commentaires

0
votes

La version Linq peut être quelque chose comme ceci (si vous voulez un code concis):

List<A> result = inputList                       // For each item in inputList
  .Select(item => new A() {                      // Create A instance
     myDict = new Dictionary<string, string>() { // Assign myDict within A by a dictionary
       {"elem1", item.elem1},                    // Which has 4 items
       {"elem2", item.elem2},
       {"elem3", item.elem3},
       {"elem4", item.elem4}, 
     }
   })
  .ToList();                                       // Materialize as a List<A>

Est-ce plus (ou moins) lisible que le code original une question ouverte.


0 commentaires