2011-02-05 70 views
8

我想使用反射将项目添加到通用列表。在方法“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(??????) 
      } 
     }  
    } 
} 

任何意见/建议?

+0

什么类型是MyBaseCollection?它是否类似于名单?并非所有实现IEnumerable的类都保证有一个Add方法。 – JoeyRobichaud 2011-02-05 23:10:03

+0

@JoeRobich:MyBaseCollection是自己的收集实现,它是派生自IList ,即使答案为列表应解决我的问题... – kayak 2011-02-05 23:14:49

回答

18

我想你想:

// 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 }); 

既然你不知道是什么该集合的元素类型将会是(可能是Car,Bike,Cycle等),你会发现很难找到有用的演员。例如,虽然你说集合肯定是实现IList<SomeMyBaseClassSubType>,但这并不是那么有用,因为IList<T>不是协变的。当然,铸造到IEnumerable<MyBaseClass>应该成功,但这不会帮助你,因为它不支持突变。另一方面,如果您的集合类型实现了非通用类型IListICollection类型,则转换为这些类型可能会派上用场。

但是如果你确保该集合将实现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); 
+0

它解决了......, – kayak 2011-02-05 23:24:19

+0

添加项目到IList一定会解决,但在我的情况下,我需要输入到IEnumerable bcos ..我有一个泛型类型的基类..“IList cln =(IList )pi.GetValue(this,null);”...所以你的第一个建议解决了...... 。(我转换为其他编码要求的ienumerable) – kayak 2011-02-05 23:32:36

0

开始与typeof<List<>>.GetMethods,你不调用属性的方法,但是属性的类型的方法

0

你能不能避免反光一起并使用:

List<MyBaseClass> lstCar { get; set; } 

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

你也可以考虑使用一个接口或抽象方法...

4

作为一种替代方案......只是不要;考虑非泛型IList接口:

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

虽然不是所有的泛型集合强制性来实现IList,他们几乎都这样做,因为它支撑着这么多的核心框架的代码。