Добавить элемент в общий список / коллекцию, используя отражение - PullRequest
8 голосов
/ 06 февраля 2011

Я хочу добавить элемент в общий список, используя отражение.В методе «DoSomething» я пытаюсь завершить следующую строку

pi.PropertyType.GetMethod("Add").Invoke(??????)

, но я получаю различные виды ошибок.

Ниже приведен мой полный код

public class MyBaseClass
{        
    public int VechicleId { get; set; }        
}    
public class Car:MyBaseClass
{
    public string Make { get; set; }
}    
public class Bike : MyBaseClass
{
    public int CC { get; set; }
}        
public class Main 
{
    public string AgencyName { get; set; }
    public MyBaseCollection<Car> lstCar {get;set;}

    public void DoSomething()
    {
        PropertyInfo[] p =this.GetType().GetProperties();
        foreach (PropertyInfo pi in p)
        {
            if (pi.PropertyType.Name.Contains("MyBaseCollection"))
            {
                //Cln contains List<Car>
                IEnumerable<MyBaseClass> cln = pi.GetValue(this, null) as IEnumerable<MyBaseClass>;

                **//Now using reflection i want to add  a new car to my object this.MyBaseCollection**
                pi.PropertyType.GetMethod("Add").Invoke(??????)
            }
        }    
    }
}

Есть идеи / предложения?

Ответы [ 4 ]

18 голосов
/ 06 февраля 2011

Я думаю, что вы хотите:

// Cast to IEnumerable<MyBaseClass> isn't helping you, so why bother?
object cln = pi.GetValue(this, null);

// Create myBaseClassInstance. 
// (How will you do this though, if you don't know the element-type?)
MyBaseClass myBaseClassInstance = ...

// Invoke Add method on 'cln', passing 'myBaseClassInstance' as the only argument.
pi.PropertyType.GetMethod("Add").Invoke(cln, new[] { myBaseClassInstance } );

Поскольку вы не знаете, каким будет тип элемента коллекции (может быть «Автомобиль», «Велосипед», «Цикл» и т. Д.), Вам будет сложно найти полезный состав. Например, хотя вы говорите, что коллекция будет определенно реализовывать IList<SomeMyBaseClassSubType>, это не так уж и полезно, поскольку IList<T> не является ковариантным. Конечно, приведение к IEnumerable<MyBaseClass> должно успешно, но это не поможет, поскольку не поддерживает мутации. С другой стороны, если в вашем типе коллекции реализованы неуниверсальные типы IList или ICollection, приведение к ним может оказаться полезным.

Но если вы уверены , что коллекция будет реализовывать IList<Car> (т.е. вы заранее знаете тип элемента коллекции), все будет проще:

// A much more useful cast.
IList<Car> cln = (IList<Car>)pi.GetValue(this, null);

// Create car.
Car car = ...

// The cast helped!
cln.Add(car);
4 голосов
/ 06 февраля 2011

Как альтернатива ... Просто не надо; рассмотрим неуниверсальный интерфейс IList:

IList list = (IList) {... get value ...}
list.Add(newItem);

Хотя не является обязательным для всех родовых коллекций для реализации IList, они в значительной степени все делают, поскольку он лежит в основе такого большого количества базового кода фреймворка.

0 голосов
/ 06 февраля 2011

Не могли бы вы просто избежать отражения и использовать:

List<MyBaseClass> lstCar { get; set; }

lstCar.Add((MyBaseClass)new Car());

Вы также можете рассмотреть возможность использования интерфейса или абстрактных методов ...

0 голосов
/ 06 февраля 2011

начинайте с typeof<List<>>.GetMethods, вы вызываете не метод свойства, а метод типа свойства

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...