2010-11-16 16 views
7

Próbowałem dodać elementy do IList poprzez refleksję, ale podczas wywoływania metody "Dodaj" błąd został zgłoszony "ref. Obiektu nie jest ustawiony". Podczas debugowania dowiedziałem się, że GetMethod ("Add") zwrócił referencję NULL.Dodawanie pozycji do listy <T> przy użyciu refleksji

Type objTyp = typeof(MyObject); //HardCoded TypeName for demo purpose 
var IListRef = typeof (List<>); 
Type[] IListParam = {objTyp};   
object Result = IListRef.MakeGenericType(IListParam); 

MyObject objTemp = new MyObject(); 
Result.GetType().GetMethod("Add").Invoke(Result, new[] {objTemp }); 

Proszę o pomoc.

+0

Pracowałem trochę z refleksją jakiś czas temu i doszedłem do wniosku, że nie lubię przeciążenia 'GetMethod (string)', ponieważ nigdy nie wiedziałem, czy to powróci. Spróbuj raczej użyć 'GetMethod (string, Type [])' lub 'GetMethod (string, BindingFlags)'. Może nie sprawi, że to zadziała, i może po prostu bym był paranoikiem, ale pamiętam, że wcześniej miałem wiele problemów z podobnymi problemami. – Alxandr

Odpowiedz

22

Starasz się znaleźć metodę Add w Type, a nie w List<MyObject> - a potem starasz się wywołać go na Type.

MakeGenericType zwraca typ, a nie instancję tego typu. Jeśli chcesz utworzyć instancję, zwykle jest to właściwa droga. Spróbuj tego:

Type objTyp = typeof(MyObject); //HardCoded TypeName for demo purpose 
var IListRef = typeof (List<>); 
Type[] IListParam = {objTyp};   
object Result = Activator.CreateInstance(IListRef.MakeGenericType(IListParam)); 

MyObject objTemp = new MyObject(); 
Result.GetType().GetMethod("Add").Invoke(Result, new[] {objTemp }); 

(Chciałbym również zasugerować, że zaczniesz następujące konwencje nazw zmiennych, ale to osobna kwestia).

+0

Dziękuję bardzo, teraz działa. Brakowało mi połączenia z "Activator.CreateInstance". – AbrahamJP

0

Masz tylko stworzył typ rodzajowy, nie utworzono instancję typu. Masz typ listy, ale nie masz listy.

Result variabled zawiera Type przedmiotów, aby Result.Gettype() zwraca same jak typeof(Type). Próbujesz znaleźć metodę Add w klasie Type, a nie na liście.

mógłbyś nie używać rodzajowych zamiast odbicia, np .:

public static List<T> CreateListAndAddEmpty<T>() where T : new() { 
    List<T> list = new List<T>(); 
    list.Add(new T()); 
    return list; 
} 
+0

Rozwiązanie oparte na Generics, które zasugerowałeś, było trafne. Powodem, dla którego nie zdecydowałem się na generyczne, było to, że metoda PropertyInfo.SetValue nie akceptowała ogólnych odwołań do parametrów, inaczej zdecydowanie zdecydowałbym się na wersję Generics. – AbrahamJP

3
private static void Test() 
    { 
     IList<Guid> list = CreateList<Guid>(); 
     Guid objTemp = Guid.NewGuid(); 
     list.Add(objTemp); 
    } 

    private static List<TItem> CreateList<TItem>() 
    { 
     Type listType = GetGenericListType<TItem>(); 
     List<TItem> list = (List<TItem>)Activator.CreateInstance(listType); 
     return list; 
    } 

    private static Type GetGenericListType<TItem>() 
    { 
     Type objTyp = typeof(TItem); 
     var defaultListType = typeof(List<>); 
     Type[] itemTypes = { objTyp }; 
     Type listType = defaultListType.MakeGenericType(itemTypes); 
     return listType; 
    } 

IList.Add (pozycja obiektu); => możesz użyć metody Dodaj w interfejsie IList zamiast Odbicia.

+0

Nie działa. 'IList Result = (IList) IListRef.MakeGenericType (IListParam);' throws 'InvalidCastException Nie można rzucić obiektu typu" System.RuntimeType ", aby wpisać" System.Collections.IList ". ' –

+1

Tak, masz rację Alex, dzięki twojemu ostrzeżeniu. Brakowało mi, że zapomniałem utworzyć instancję. I edytuję kod, a w tym czasie jest on testowany i działa;))) – Doctor

Powiązane problemy