使用反射做一个根据sp名调用相应sp的方法,直接看代码
public SUNCRM_GetAgentResult GetAgentBySPNameAndParam(string spName, string[] param, ref string pMsg) { SUNCRM_GetAgentResult _rtnList = new SUNCRM_GetAgentResult(); try { Type type = typeof(Place_CRMDataContext); object reflectObj = Activator.CreateInstance(type); MethodInfo method = type.GetMethod(spName); object data = method.Invoke(reflectObj, param);//原始方法返回的是ISingleResult<具体类型>的对象,被转换为object了 //使用这段代码替换下面的switch string attributeName = spName.Substring(15); PropertyInfo propertyInfo = typeof(SUNCRM_GetAgentResult).GetProperty(attributeName); object objData = Convert.ChangeType(data, propertyInfo.GetType());//报错,错误信息"对象必须实现 IConvertible"。 propertyInfo.SetValue(_rtnList, objData); //switch是迫不得已的做法,如果以後增加了sp还要修改,虽然现在也还要修改模型类SUNCRM_GetAgentResult switch(spName) { //有几十个sp,这里只列举几个 case "SUNCRM_GetAgentCodeIn": _rtnList.CodeIn = ((ISingleResult<SUNCRM_GetAgentCodeInResult>)data).ToList(); break; case "SUNCRM_GetAgentProfile": _rtnList.Profile = ((ISingleResult<SUNCRM_GetAgentProfileResult>)data).ToList(); break; case "SUNCRM_GetAgentFollow": _rtnList.Follow = ((ISingleResult<SUNCRM_GetAgentFollowResult>)data).ToList(); break; case "SUNCRM_GetAgentType_tags": _rtnList.Type_tags = ((ISingleResult<SUNCRM_GetAgentType_tagsResult>)data).ToList(); break; } pMsg = spName; return _rtnList; } catch(Exception _ex) { pMsg ="sp name:" + spName + ",error message:" + _ex.Message; AcsUtils.WriteEvtLog(spName, _ex); throw new Exception(_ex.Message); } }
现在最关键的问题是如何把原始类型为ISingleResult<具体类型>的object对象转换为List<具体对象>(这个具体类型是不确定的,参考switch)本来原始类型直接使用ToList()就能搞定,但是被转换为object了没有ToList()。
ISingleResult<具体类型> originalData = GetDataFromWcf(); object tempData = originalData; List<具体类型> finalData = MyChangeType(tempData);
现在的问题是如何实现这个转换类型的MyChangeType()方法
补充:以下是属性名和sp名和具体类型的关系
属性名:"X"
sp名:"SUNCRM_GetAgent" + "X"
具体类型名:"SUNCRM_GetAgent" + "X" + "Result"
尝试各路方法无效,人工置顶一波,坐等大腿
自己解決了,绕开了问题。原先SUNCRM_GetAgentResult中定义的都是List<具体类型>的属性,既然无法转换成list,那就定义成原始的ISingleResult<具体类型>的属性好了,反正客户端那边也是要调用ToList()方法的。这样拿到数据data后直接赋值就好,去掉数据转换的这行object objData = Convert.ChangeType(data, propertyInfo.GetType()),去掉整个switch,得到最终的代码。本质上还是没有解决标题所描述的问题,只是绕开了。
用泛型?`
使用泛型的话传参是个问题,要根据sp名来传递不同的对象,这样还不如用switch。
@军长_cnblogs: 不用泛型外面不知道是什么类型.
@吴瑞祥: 这是个wcf接口,接口调用方根据自己的需要从_rtnList中的具体属性获得值,参考switch,现在switch是已经暂时可以实现所要的效果的了。
你说的十几个spName的话,用switch那一段写的太冗余了,传过来的spName可以放在同一个namespace下,通过反射全路径指向ISingleResult<typeOf(namespace路径.spName)>,这样可以不用switch。
能否给出代码?我试着这样写
object objData = (ISingleResult<typeof(SUNCRM_GetAgentCodeInResult)>)data;
vs会提示错误
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Type type = typeof(A); object reflectObj = Activator.CreateInstance(type); MethodInfo method = type.GetMethod("CCC"); object data = method.Invoke(reflectObj,new string[]{"aaaaaaaaaa"});//原始方法返回的是ISingleResult<具体类型>的对象,被转换为object了 if (data is IList<B>) { Console.WriteLine("这个是B类型"); } if (data is IList<C>) { Console.WriteLine("这个是C类型"); } } } class A { public IList<B> BBB(string h) { Console.WriteLine("AAAAAAAAAAAAAAA"+h); B b = new B(); b.Name = "HelloWorld"; List<B> list = new List<B>(); list.Add(b); return list; } public IList<C> CCC(string h) { Console.WriteLine("AAAAAAAAAAAAAAA" + h); C b = new C(); b.Name = "HelloWorld"; List<C> list = new List<C>(); list.Add(b); return list; } } public class B { public string Name { get; set; } } public class C { public string Name { get; set; } } public class D { public string Name { get; set; } } }
有几十个类型的时候你这里不是要判断几十次。。。那感觉还不如switch