web-dev-qa-db-fra.com

Convertir le type anonyme en classe

J'ai un type anonyme dans une liste ANBook:

var anBook=new []{

new {Code=10, Book ="Harry Potter"},
new {Code=11, Book="James Bond"}
};

Est à éventuellement possible de le convertir en une liste avec la définition suivante de Clearbook:

public class ClearBook
{
  int Code;
  string Book; 
}

en utilisant une conversion directe, c'est-à-dire sans boucle via ANBOOK?

24
Graviton

Eh bien, vous pouvez utiliser:

var list = anBook.Select(x => new ClearBook {
               Code = x.Code, Book = x.Book}).ToList();

mais non, il n'y a pas de support de conversion directe. De toute évidence, vous aurez besoin d'ajouter des accesseurs, etc. (ne faites pas les champs publics) - je suppose que:

public int Code { get; set; }
public string Book { get; set; }

Bien sûr, l'autre option est de commencer avec les données comment vous le souhaitez:

var list = new List<ClearBook> {
    new ClearBook { Code=10, Book="Harry Potter" },
    new ClearBook { Code=11, Book="James Bond" }
};

Il y a aussi des choses que vous pourriez faire pour mapper les données avec réflexion (peut-être utiliser un Expression pour compiler et mettre en cache la stratégie), mais cela n'en vaut probablement pas la peine.

44
Marc Gravell

Comme le dit Marc, cela peut être fait avec des arbres de réflexion et d'expression ... et comme la chance l'avoir, il y a une classe dans méthode de contrôle qui fait exactement cela. Cependant, en consultant votre question plus étroitement, il semble que vous souhaitiez appliquer cette conversion à une collection (tableau, liste ou autre) sans boucle . Cela ne peut pas fonctionner. Vous convertissez d'un type à un autre - ce n'est pas comme si vous pouvez utiliser une référence au type anonyme comme s'il s'agit d'une référence à ClearBook.

Pour donner un exemple de la façon dont la classe de propriétéCopy fonctionne cependant, vous auriez juste besoin de:

var books = anBook.Select(book => PropertyCopy<ClearBook>.CopyFrom(book))
                                 .ToList();
11
Jon Skeet

Qu'en est-il de ces extensions? Appelez simple la .tononanonymouslist sur votre type anonyme ..

public static object ToNonAnonymousList<T>(this List<T> list, Type t)
    {
        //define system Type representing List of objects of T type:
        Type genericType = typeof (List<>).MakeGenericType(t);

        //create an object instance of defined type:
        object l = Activator.CreateInstance(genericType);

        //get method Add from from the list:
        MethodInfo addMethod = l.GetType().GetMethod("Add");

        //loop through the calling list:
        foreach (T item in list)
        {
            //convert each object of the list into T object by calling extension ToType<T>()
            //Add this object to newly created list:
            addMethod.Invoke(l, new[] {item.ToType(t)});
        }
        //return List of T objects:
        return l;
    }
    public static object ToType<T>(this object obj, T type)
    {
        //create instance of T type object:
        object tmp = Activator.CreateInstance(Type.GetType(type.ToString()));

        //loop through the properties of the object you want to covert:          
        foreach (PropertyInfo pi in obj.GetType().GetProperties())
        {
            try
            {
                //get the value of property and try to assign it to the property of T type object:
                tmp.GetType().GetProperty(pi.Name).SetValue(tmp, pi.GetValue(obj, null), null);
            }
            catch (Exception ex)
            {
                Logging.Log.Error(ex);
            }
        }
        //return the T type object:         
        return tmp;
    }
5
Christian Casutt