问题描述
usingSystem;usingSystem.Collections.Generic;usingSystem.Collections;usingSystem.Linq;usingSystem.Text;//需要引用Json.net的类库。http://www.newtonsoft.com/json可以下载,也可以屏蔽代码中演示用的json解析部分//usingNewtonsoft.Json;//usingNewtonsoft.Json.Linq;//usingNewtonsoft.Json.Serialization;usingSystem.Reflection;usingSystem.Diagnostics;namespaceqq20662.WeiXin.Tests.Models{//IList反射的操作的演示,请查看标有??????的行次。//IList反射不出Add方法。奇怪。publicclassReflectionIList{publicvoidtest1(){//如果普通生成可以这样:AAa1=newAA();a1.Ap1="xx";BB_1b1=newBB_1();b1.Bp1=115;BB_2b2=newBB_2();b2.Bp1=171;//注意这里可以替换为其他实现了IList接口的用户自定义类a1.AaBb=newList<IBB>();a1.AaBb.Add(b1);a1.AaBb.Add(b2);//如何通过反射生成AA的对象。//当AaBb中无法确定使用那个具体类来实例化,允许直接使用BB_1stringjString=@"{""Ap1"":""xx"",""AaBb"":[{""Bp1"":115},{""Bp1"":171}]}";//假定已经把json全部解析完毕了。这几行可以屏蔽//JObjectjo=JObject.Parse(jString);Debug.Print(typeof(AA).Assembly.GetName().Name);//这里可以得到qq20662.WeiXin.Tests,在每个人的项目中都不一样的,可以复制出来,下面要用的Debug.Print(typeof(AA).FullName);//这里可以得到qq20662.WeiXin.Tests.Models.AA,在每个人的项目中都不一样的,可以复制出来,下面要用的//假定可以用工厂模式从配置文件加载AA的typefullnameobjectoa1=Activator.CreateInstance(Assembly.Load("qq20662.WeiXin.Tests").GetType("qq20662.WeiXin.Tests.Models.AA"));//获取oa1的所有属性PropertyInfo[]props=oa1.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance);foreach(PropertyInfopropinprops){//这里可以与json做匹配,看属性名是否符合。//比较简单,就忽略了。if(prop.Name=="AaBb"){Typet2=prop.PropertyType.GetGenericArguments().First();//得到泛型中的类型,如IBBType[]typeArgs={t2};//生成泛型参数//假定提供参数,可以用List<>来实现IList接口TypealgTypeGen=typeof(List<>);//生成列表TypealgType=algTypeGen.MakeGenericType(typeArgs);//生成具体的泛型列表。objectoAaBb=Activator.CreateInstance(algType);//下面省略用反射获取BB_1类型的对象。基本根上面差不多,可以用工厂类根据json和预先设置的字符串来返回实例BB_1b3=newBB_1();b3.Bp1=9999;MethodInfoaddMethod=prop.PropertyType.GetMethod("Add");//??????下面这行就比较奇怪了,按道理IList的属性应该有Add方法,但是这里返回的是null,未获取到。Debug.Print((addMethod==null).ToString());//这里返回true表示没有add方法,奇怪。MethodInfo[]ms=prop.PropertyType.GetMethods();foreach(MethodInfomIteminms){Debug.Print(mItem.Name);}//??????上面循环的输出结果是下面这些。//get_Item//set_Item//IndexOf//Insert//RemoveAt//下面这行的返回值是System.Collections.Generic.IList`1[[qq20662.WeiXin.Tests.Models.IBB,qq20662.WeiXin.Tests,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null]]//应该是对的,那Add方法到哪里去了?IList.Add方法应该有的呀?Debug.Print(prop.PropertyType.FullName);}}}}publicclassAA{publicstringAp1;protectedIList<IBB>_aaBb;publicIList<IBB>AaBb{get{return_aaBb;}set{_aaBb=value;}}}publicinterfaceIBB{intBp1{get;set;}voidAdd();}publicclassBB_1:IBB{publicintBp1{get;set;}publicvoidAdd(){}}publicclassBB_2:IBB{publicintBp1{get;set;}publicvoidAdd(){}}}
解决方案
解决方案二:
看到版主勋章,我还以为这是教学帖呢
解决方案三:
MethodInfoaddMethod=prop.PropertyType.GetMethod("Add");改为:MethodInfoaddMethod=oAaBb.GetType().GetMethod("Add");
解决方案四:
看了下你的数据类型定义“publicIList<IBB>AaBb”,你这个是定义的接口啊,因此你的prop.PropertyType是IList而不是List,两个完全不同的类型,虽然有继承关系,但实际需要反射的是继承后的List类的Add方法,对接口类型本身进行反射是得不到任何执行方法的。
解决方案五:
二楼说得对,我看了元数据,的确是,那我应该如何才能用反射实现IList的add方法呢?即使他是继承的,总能用反射实现吧?