首页 新闻 搜索 专区 学院

c#反射的问题,急用,麻烦大家帮我解决一下

0
悬赏园豆:5 [已关闭问题] 关闭于 2010-11-11 11:24

public Class A

{

  public int? Id{get; set;}

  public string Name{get;set;}

  public B b{get;set;}

}

public Class B

{

  public int? Id{get;set;}

  public string Name{get;set;}

}

public Class C

{

  public T AnyOne<T>(T obj,string tableName,string ConnSr)

  {

    string sql = "SELECT * FROM {0} {1} ";

    SqlConnection Conn = null;
           DataSet ds = null;
           try
           {
               //反射一个对象
               Type type = obj.GetType();
               PropertyInfo[] ps = type.GetProperties();
               StringBuilder sb = new StringBuilder();
               //查看对象的属性
               foreach (var p in ps)
               {

      //上面有个A类和B类,A类里面有个属性是B类,

      //我的问题是,在反射A类的过程中如何去实例化B类,给B类赋值

      //目前,如果用判断类型,那么我是可以实现的,但是问题是,我model层里面有很多个

      //类,都是有关系的,因为都是数据库的映射类,主外关系有很多,所以,用判断

      //类型的话,太多,太麻烦,我想请问各位大虾,有没有更好的解决办法?

      //还有,我这个方法用的循环,我觉得很多,有没有更好的办法可以解决?
                   var value = p.GetValue(obj, null);
                   //判断属性是否为空
                   if (value != null)
                   {
                       sb.AppendFormat(" {0}='{1}' AND ", p.Name, value.ToString());
                   }
               }
               string v = sb.ToString();
               sql = string.Format(sql, tabName, v.Length > 0 ? " WHERE " + v.Substring(0, v.Length - 4) : "");
               //存放到一个DataSet里面
               SqlDataAdapter adapter = new SqlDataAdapter(sql,ConnStr);
               ds = new DataSet(tabName);
               adapter.Fill(ds);
               //读取数据,存放到T里面
               if (ds.Tables[0].Rows.Count > 0)
               {
                   for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
                   {
                       foreach (var p in ps)
                       {
                           if (ds.Tables[0].Columns[i].ColumnName.ToLower() == p.Name.ToLower())
                           {
                               //判断是否为空值
                               if (!(ds.Tables[0].Rows[0][i] is DBNull))
                               {
                                   p.SetValue(obj, ds.Tables[0].Rows[0][i], null);
                                   break;  
                               }
                           }
                       }
                   }
               }

  }

}

|ī笨笨﹎ヤ的主页 |ī笨笨﹎ヤ | 初学一级 | 园豆:2
提问于:2010-11-11 00:50
< >
分享
所有回答(2)
0

总体来说没看明白。

因为"SELECT * FROM {0} {1} ";返回一张表而已。提醒一下这里,通常都不建议 “select * “的,应该是用到哪几个字段,才返回哪几个字段。

请将你要返回哪些字段分别对应类型A、类型B的哪些属性再说的详细一下。

mywork | 园豆:475 (菜鸟二级) | 2010-11-11 08:13
是这样的 SQL语句是SELECT A.id,A.Name,B.Name FROM A,B WHERE A.bid=B.id 我查询的是表A和表B的东西,问题是,我怎么把查询到的这些值赋给Model里面的实体类? 如果是单独一张表,我可以判断字段名是否相同,但是是多表查询,返回的一些字段在Model里面是找不到属性名的,得通过实例A里面的B属性才可以看到。
支持(0) 反对(0) |ī笨笨﹎ヤ | 园豆:2 (初学一级) | 2010-11-11 10:53
楼主的问题较难解决。 因为你实际上可以跟踪看一下, adapter.Fill(ds); 之后那个DataTable列里面的返回值。 SELECT A.id,A.Name,B.Name 得到的结果是DataTable里面有两个Name,怎么构建“通用”的映射关系?(我料想楼主是想做一个通常的查询方法的吧。)如果硬编码说 A.ID = table.Rows[x][0]; A.Name = table.Rows[x][1]; B.Name = table.Rows[x][2];估计是没问题的。但是想做一个通用的东西,得另想办法。 要解决此问题要么使用 SELECT A.id,A.Name,B.Name as Name2 这种别名的方式,要么硬编码。我是没想到有别的办法。 关于反射数据为实例对象,我这儿有一个别人的方法,是IDataRecord对象转换为实体对象,你可以参考着用。 /// /// EntityBuilder实体类生成代码 /// public class EntityBuilder<Entity> { private delegate Entity Load(IDataReader dataReader); private Load handler; private EntityBuilder() { } public Entity Build(IDataReader reader) { MethodInfo _me=handler.Method; _me.ToString(); return handler(reader); } public static EntityBuilder<Entity> CreateBuilder(IDataRecord reader) { EntityBuilder<Entity> result = new EntityBuilder<Entity>(); DynamicMethod method = new DynamicMethod("CreateBuilder", typeof(Entity), new Type[] { typeof(IDataReader) }, typeof(Entity), true); ILGenerator generator = method.GetILGenerator(); generator.DeclareLocal(typeof(Entity)); generator.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc_0); MethodInfo getValue = reader.GetType().GetMethod("get_Item", new Type[] { typeof(int) }); for (int i = 0; i < reader.FieldCount; i++) { PropertyInfo propertyInfo = typeof(Entity).GetProperty(reader.GetName(i)); if (propertyInfo != null && propertyInfo.GetSetMethod() != null) { Label label = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, reader.GetType().GetMethod("IsDBNull")); generator.Emit(OpCodes.Brtrue, label); generator.Emit(OpCodes.Ldloc_0); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, i); generator.Emit(OpCodes.Callvirt, getValue); generator.Emit(OpCodes.Unbox_Any, reader.GetFieldType(i)); generator.Emit(OpCodes.Cal
支持(0) 反对(0) mywork | 园豆:475 (菜鸟二级) | 2010-11-11 14:49
而且使用public class EntityBuilder<Entity>这种Emit方式,比简单用反射效率要更好一些。
支持(0) 反对(0) mywork | 园豆:475 (菜鸟二级) | 2010-11-11 14:51
0

看看NHibernate是怎么实现的,自己写这个好像挺麻烦,我也用反射实现获Model,新增修改等,但楼主问题。。。欺待中..

paaple | 园豆:15 (初学一级) | 2010-11-11 08:24
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册