2009-09-02 6 views
1

Je dois pouvoir accéder à une propriété par réflexion et, sachant que cette propriété est IEnumerable, ajouter un objet à cette propriété.Ajouter un objet à un IEnumerable <> via la réflexion

Quelque chose comme ceci:

Object o; 
MemberInfo m; 

Array arr; // Except use IEnumerable, may have to take account of value/ref types 
arr = (Array)((PropertyInfo)m).GetValue(o, null); } 

List<o.GetType()> newArr = new List<o.GetType()>(); /* fails */ 
newArr.AddRange(arr); 
newArr.Add(o); 

((PropertyInfo)m).SetValue(o, newArr.ToArray(), null); 

Pouvez-vous me aider où je vais mal :-)

Solution:

Voir acceptées commentaires de réponse. Aussi (Get the actual type of a generic object parameter) est d'aide.

Répondre

2

Il semble que vous demandiez essentiellement comment créer un List<T> basé sur un type inconnu au moment de la compilation. Pour cela, vous devrez utiliser un peu plus magique réflex:

Type genericListType = typeof(List<>); 
Type listType = genericListType.MakeGenericType(o.GetType()); 
object listInstance = Activator.CreateInstance(listType); 

Cela créerait un List<T> sur un type d'exécution.

Mais vraiment, votre code serait beaucoup plus simple si vous utilisez simplement ArrayList:

ArrayList list = new ArrayList(arr); 
list.Add(o); 
Array newArray = list.ToArray(o.GetType()); 
+0

Merci pour me pointant dans la bonne direction. Malheureusement, je ne pense pas que je peux écrire une solution générique qui traite des propriétés de string [], List , List (même en omettant Dictionary ). Le problème est que vous ne pouvez pas lancer listInstance à une liste afin d'ajouter et même si j'ai créé un IEnumerable je ne peux pas remplacer un champ de propriété de type Liste avec ce nouvel objet créé. –

+1

Est-il possible de prendre du recul et de considérer le problème global que vous êtes en train de résoudre, pour voir si vous pouvez utiliser une approche plus compilable en temps de compilation? La réflexion est puissante mais finit par être compliquée et difficile à maintenir. Si vous ne pouvez pas changer ce que vous faites, il existe toujours un moyen de prendre en charge tout ce que vous avez mentionné, il nécessite juste un code de réflexion laide. J'oublierais probablement de remplacer la référence sous-jacente et je rechercherais simplement une méthode Add que je pourrais utiliser (par exemple, propertyType.GetMethod ("Add")), puis la gestion de cas particuliers de tableaux. – bobbymcr

+0

Il s'agit de mapper de manière générique des classes de code sur un fichier de données, donc la réflexion doit être la réponse. Merci, cependant, en combinaison votre idée et cette question (http://stackoverflow.com/questions/1371347/get-the-actual-type-of-a-generic-object-parameter/1371378#1371378) + manipulation des tableaux aidé :-) –

4

Une fois que vous avez un type IEnumerable, utilisez quelque chose comme ceci à ajouter à ce:

public static IEnumerable<T> Append<T>(this IEnumerable<T> original, T next) 
{ 
    foreach (T item in original) yield return item; 
    yield return next; 
} 

public static IEnumerable<T> Append<T>(this IEnumerable<T> original, params T[] next) 
{ 
    foreach (T item in original) yield return item; 
    foreach (T item in next) yield return item; 
} 

public static IEnumerable<T> Append<T>(this IEnumerable<T> original, IEnumerable<T> next) 
{ 
    foreach (T item in original) yield return item; 
    foreach (T item in next) yield return item; 
} 
+0

Merci pour cela :-) –

+0

Bien que vous devez renommer ces méthodes Ajouter

Questions connexes