实体类:
[Serializable] 
public class ProductInfo
{
  string Code;
  string Name;  
}
... 有很多类似的实体类.数据访问类:
public class ProductDa
{
        public List<ProductInfo> GetModels()
        {
            List<ProductInfo> list = new List<ProductInfo>();
            using (SqlDataReader rdr = SqlHelper.ExecuteReader(this.connectionString ,CommandType.StoredProcedure,SELECT,null))
            {
                while (rdr.Read())
                {
                    ProductInfo tmp = new ProductInfo(
                        rdr.GetString(0),
                        rdr.GetString(1),
                    list.Add(tmp);
                    line++;
                }
            }
            return list ;
        }
}现在问题是,针对每一个实体类的数据访问类都要写这样重复的代码,(只是实体类不同,实体构造函数参数不同).有没有可能用泛型解决这样的问题,如上只要一个 
List<T> GetModels() , 然后传入不同的实体类型即可.如可则在实际应用中可省很多代码.请做过的朋友给点思路,请对此感兴趣的朋友帮忙顶顶,谢谢!

解决方案 »

  1.   

    定义基类,,public class BaseDAL<IData> 
    然后其它的数据访问类继承基类....并传入实体类给泛型参数...
      

  2.   

    //提供点思路,用ArrayList
    [Serializable]
    public class ProductInfo
    {
        public string Code;
        public string Name;
    }public ArrayList GetModels(Type AType)
    {
        if (AType == null) return null;
        object vObject = Activator.CreateInstance(AType);
        ArrayList Result = new ArrayList();
        Result.Add(vObject);
        int i = 0;
        foreach (FieldInfo vFieldInfo in AType.GetFields())
        {
            vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
            i++;
        }
        return Result;
    }private void button1_Click(object sender, EventArgs e)
    {
        ArrayList vArrayList = GetModels(typeof(ProductInfo));
        Text = ((ProductInfo)vArrayList[0]).Name;
    }
      

  3.   

    michael_zy(枫林) ( )  能否再细点, 关键就是传入泛型参数后不如何根据不同的实体处理.谢谢  zswang(伴水清清)(专家门诊清洁工) ( ) 的提示,我试试.
      

  4.   

    foreach (FieldInfo vFieldInfo in AType.GetFields())
        {
            vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
            i++;
        }这段循环怎么保证字段和变量能一一对应阿?
      

  5.   

    >lookatliu:
    >这段循环怎么保证字段和变量能一一对应阿?这个对应是声明类型时做的事情michael_zy提供的方案也不错,通过继承同一类型实现
    在重载方法设计中可以考虑处理和数据库字段对应的关系
      

  6.   


    foreach (FieldInfo vFieldInfo in AType.GetFields())
    {
    vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
    i++;
    }这段循环怎么保证字段和变量能一一对应阿?
    ============================================
    可以这样改一下
    using (SqlDataReader rdr = SqlHelper.ExecuteReader(this.connectionString ,CommandType.StoredProcedure,SELECT,null))
    vFieldInfo.SetValue(vObject, rdr[vFieldInfo.Name]);命名类的实例名时保证跟数据库字段名一致就OK了。
      

  7.   

    michael_zy提供的方案不结合反射好像是不太好实现自动化的
    因为楼主的实体类之间并不一定有关系,让他们派生自共同的主先,只能保证一定程序上的强类型。我的意见是结合michael_zy和zswang的意见做
      

  8.   

    namespace PKPM.UserPage
    {
        public class EntityInputControl<T> : EntityControlBase<T>
        {        private T _PageEntity;        /// <summary>
            /// 数据保存,可以重写该方法
            /// </summary>
            /// <returns></returns>
            public virtual bool SaveData()
            {
                bool flag = false;
                T objType = this.PageEntity;
                //调用WebService保存数据对象
                return flag;
            }        /// <summary>
            /// 获取用户控件业务实体的数据对象
            /// </summary>
            public virtual T PageEntity
            {
                get
                {
                    if (_PageEntity != null)
                        return this._PageEntity;
                    ArrayList ctlList = new ArrayList();
                    //遍历用户控件的数据子控件
                    foreach (System.Web.UI.Control ctl in this.Controls)
                    {
                        if ( this.IsEntityProperty( ctl ) )
                        {
                            ctlList.Add(ctl);
                        }
                    }
                    //数据实体属性集合
                    PropertyInfo[] infoArr = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                    object objData = Activator.CreateInstance(typeof(T));
                    //遍历数据实体对象,并设置数据实体的属性值
                    for (int num = 0; num < infoArr.Length; num++)
                    {
                        foreach (object item in ctlList)
                        {
                            IWControl iwc = (IWControl)item;
                            if (iwc.ColumnName.Equals(infoArr[num].Name))
                            {
                                infoArr[num].SetValue(objData, iwc.GetValue(), null);
                                ctlList.Remove(item);
                                break;
                            }
                        }
                    }
                    ctlList = null;
                    _PageEntity = (T)objData;
                    return _PageEntity;
                }
            }    }
    }
      

  9.   

    public object Query<T>(string filter)
            {
                try
                {
                    MetaData md = MetaDataManager.GetMetaData(typeof(T));
                    QueryCommandBuilder qcBuilder = new OleDb.OleDbQueryCommandBuilder();
                    qcBuilder.EntityType = md.EntityType;
                    qcBuilder.PersistType = EntityPersistType.Query;
                    qcBuilder.Filter = filter;
                    QueryCommand cmd = qcBuilder.GetQueryCommand();
                    DbDataReader reader = DAO.ExecuteDataReader(cmd.CommandText, cmd.Parameters);
                    return DbDataReaderToList<T>(reader);
                }
                catch
                {
                    return null;
                }        }#region private Method
            private object DbDataReaderToList<T>(DbDataReader reader)
            {
                List<T> list = new List<T>();
                MetaData md = MetaDataManager.GetMetaData(typeof(T));
                while (reader.Read())
                {
                    T obj = Activator.CreateInstance<T>();
                    foreach (PropertyInfo info in obj.GetType().GetProperties())
                    {
                        if (!reader.IsDBNull(reader.GetOrdinal(md.FieldMeteDatas[info.Name].ColumnName)))
                        {
                            info.SetValue(obj, reader[md.FieldMeteDatas[info.Name].ColumnName], null);
                        }
                    }
                    list.Add(obj);
                }
                return list;
            }
            #endregion
    自己程序的两个方法代码,以供参考
      

  10.   

    麻烦……
    直接定义一大堆属性,令属性与数据库字段重名,便可通过反射来创建实体类……
    如果嫌效率差,可以尝试挑刺、NInputer还有俺共同努力的结果,超强ORM转换器。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Reflection.Emit;
    using System.Reflection;namespace Ivony.Data.ObjectData
    {
      /// <summary>
      /// ORM相关操作的帮助器
      /// </summary>
      public static class ORMHelper
      {    /// <summary>
        /// 构建一个ORM转换器
        /// </summary>
        /// <typeparam name="T">转换的目标类型</typeparam>
        /// <param name="schema">数据架构</param>
        /// <res>
        /// 感谢:tiaoci、Ninputer。
        /// </res>
        /// <returns>转换器</returns>
        public static ORMDataRowConverter<T> BuildConverter<T>( DataTable schema )
        {
          DynamicMethod method = new DynamicMethod(
          "DataRowToEntity_" + schema.GetHashCode().ToString(), null,
          new Type[] { typeof( DataRow ), typeof( T ) },
          typeof( T ) );      MethodInfo DataRow_Item_get = typeof( DataRow ).GetMethod( "get_Item", new Type[] { typeof( int ) } );
          ILGenerator il = method.GetILGenerator();
          foreach ( FieldInfo field in typeof( T ).GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public ) )
          {
            string fieldName = field.Name.TrimStart( '_' );
            if ( schema.Columns.Contains( fieldName ) )
            {
              il.Emit( OpCodes.Ldarg_1 );
              il.Emit( OpCodes.Ldarg_0 );
              il.Emit( OpCodes.Ldc_I4, schema.Columns[fieldName].Ordinal );
              EmitCall( il, DataRow_Item_get );
              EmitCastObj( il, field.FieldType );
              il.Emit( OpCodes.Stfld, field );
            }
          }      il.Emit( OpCodes.Ret );      return (ORMDataRowConverter<T>) method.CreateDelegate( typeof( ORMDataRowConverter<T> ) );
        }    /// <summary>
        /// 构建一个ORM转换器
        /// </summary>
        /// <typeparam name="T">转换的目标类型</typeparam>
        /// <res>
        /// 感谢:tiaoci、Ninputer。
        /// </res>
        /// <returns>转换器</returns>
        public static ORMDataRowConverter<T> BuildConverter<T>()
        {      /*
    .method public hidebysig static void  ConvertEntity(class [System.Data]System.Data.DataRow data,
                                                        class Ivony.Data.ObjectData.Entity entity) cil managed
    {
      // 代码大小       79 (0x4f)
      .maxstack  3
      .locals init (class [System.Data]System.Data.DataColumnCollection V_0,
               class [System.Data]System.Data.DataColumn V_1)
      IL_0000:  ldarg.0
      IL_0001:  callvirt   instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataRow::get_Table()
      IL_0006:  callvirt   instance class [System.Data]System.Data.DataColumnCollection [System.Data]System.Data.DataTable::get_Columns()
      IL_000b:  stloc.0
      IL_000c:  ldloc.0
      IL_000d:  ldstr      "a"
      IL_0012:  callvirt   instance class [System.Data]System.Data.DataColumn [System.Data]System.Data.DataColumnCollection::get_Item(string)
      IL_0017:  dup
      IL_0018:  stloc.1
      IL_0019:  brfalse.s  IL_002d
      IL_001b:  ldarg.1
      IL_001c:  ldarg.0
      IL_001d:  ldloc.1
      IL_001e:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(class [System.Data]System.Data.DataColumn)
      IL_0023:  unbox.any  [mscorlib]System.Int32
      IL_0028:  stfld      int32 Ivony.Data.ObjectData.Entity::a
      IL_002d:  ldloc.0
      IL_002e:  ldstr      "b"
      IL_0033:  callvirt   instance class [System.Data]System.Data.DataColumn [System.Data]System.Data.DataColumnCollection::get_Item(string)
      IL_0038:  dup
      IL_0039:  stloc.1
      IL_003a:  brfalse.s  IL_004e
      IL_003c:  ldarg.1
      IL_003d:  ldarg.0
      IL_003e:  ldloc.1
      IL_003f:  callvirt   instance object [System.Data]System.Data.DataRow::get_Item(class [System.Data]System.Data.DataColumn)
      IL_0044:  unbox.any  [mscorlib]System.Int32
      IL_0049:  stfld      int32 Ivony.Data.ObjectData.Entity::b
      IL_004e:  ret
    } // end of method ORMHelper::ConvertEntity      */
          DynamicMethod method = new DynamicMethod( "DataRowToEntity", null, new Type[] { typeof( DataRow ), typeof( T ) }, typeof( T ) );
          ILGenerator il = method.GetILGenerator();      il.DeclareLocal( typeof( DataColumnCollection ) );
          il.DeclareLocal( typeof( DataColumn ) );      il.Emit( OpCodes.Ldarg_0 );
          EmitCall( il, typeof( DataRow ).GetProperty( "Table" ).GetGetMethod() );
          EmitCall( il, typeof( DataTable ).GetProperty( "Columns" ).GetGetMethod() );
          il.Emit( OpCodes.Stloc_0 );      foreach ( FieldInfo field in typeof( T ).GetFields( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ) )
          {
            Label label = il.DefineLabel();
            string fieldName = field.Name.TrimStart( '_' );        il.Emit( OpCodes.Ldloc_0 );
            il.Emit( OpCodes.Ldstr, fieldName );
            EmitCall( il, typeof( DataColumnCollection ).GetProperty( "Item", new Type[] { typeof( string ) } ).GetGetMethod() );        il.Emit( OpCodes.Dup );
            il.Emit( OpCodes.Stloc_1 );        il.Emit( OpCodes.Brfalse, label );        il.Emit( OpCodes.Ldarg_1 );
            il.Emit( OpCodes.Ldarg_0 );
            il.Emit( OpCodes.Ldloc_1 );        EmitCall( il, typeof( DataRow ).GetProperty( "Item", new Type[] { typeof( DataColumn ) } ).GetGetMethod() );
            EmitCastObj( il, field.FieldType );        il.Emit( OpCodes.Stfld, field );        il.MarkLabel( label );
          }      il.Emit( OpCodes.Ret );      return (ORMDataRowConverter<T>) method.CreateDelegate( typeof( ORMDataRowConverter<T> ) );
        }
        private static void EmitCastObj( ILGenerator il, Type targetType )
        {
          if ( targetType.IsValueType )
            il.Emit( OpCodes.Unbox_Any, targetType );
          else
            il.Emit( OpCodes.Castclass, targetType );
        }
        private static void EmitCall( ILGenerator il, MethodInfo method )
        {
          if ( method.IsVirtual )
            il.Emit( OpCodes.Callvirt, method );
          else
            il.Emit( OpCodes.Call, method );
        }
      }  /// <summary>
      /// 代表从DataRow中获取数据的ORM转换方法
      /// </summary>
      /// <typeparam name="T">转换的目标类型</typeparam>
      /// <param name="data">数据来源</param>
      /// <param name="entity">被写入的包含数据的实例对象</param>
      public delegate void ORMDataRowConverter<T>( DataRow data, T entity );
    }
    一般人我不告诉她……
      

  11.   

    上面这个ORM转换器还是简化了并降低了效率的,但速度也恐怖得吓人……
      

  12.   

    Ivony(授人以鱼不如授人以渔,上海谋生)
    别这么小气嘛,我也做了一个ORM方面的东西,速度还不赖,现在的主要问题就是分页不好处理,不知你有什么良策。
      

  13.   

    分页处理部分由ObjectDataPagination提供,一共牵涉到三个组件:ORM映射转换器,由ORMHelper提供帮助
    强类型分页器,ObjectDataPagination和ObjectDataCollection
    数据分页器,IDataPagination  /// <summary>
      /// 强类型数据分页器
      /// </summary>
      /// <typeparam name="T">数据类型</typeparam>
      public class ObjectDataPagination<T> : IObjectDataPagination<T>, IPaginationBase
      {    private IObjectDataConverter<T> _converter;
        private ObjectDataConvertMethod<T> _converterMethod;
        private IDataPagination _dataSource;    public ObjectDataPagination( IObjectDataConverter<T> converter, IDataPagination dataSource )
        {
          if ( converter == null )
            throw new ArgumentNullException( "converter" );
          if ( dataSource == null )
            throw new ArgumentNullException( "dataSource" );      _converter = converter;
          _dataSource = dataSource;
        }    public ObjectDataPagination( ObjectDataConvertMethod<T> converter, IDataPagination dataSource )
        {
          if ( converter == null )
            throw new ArgumentNullException( "converter" );
          if ( dataSource == null )
            throw new ArgumentNullException( "dataSource" );      _converterMethod = converter;
          _dataSource = dataSource;
        }    public int GetCount()
        {
          return _dataSource.GetCount();
        }    public IList<T> GetPage( int pageindex )
        {
          System.Data.DataTable data = _dataSource.GetPage( pageindex );      if ( _converter != null )
            return new ObjectDataCollection<T>( _converter, data );
          else
            return new ObjectDataCollection<T>( _converterMethod, data );
        }    public int PageSize
        {
          get { return _dataSource.PageSize; }
        }
        public IDataPagination DataPagination
        {
          get { return _dataSource; }
        }
        System.Collections.IEnumerable IPaginationBase.GetPage( int pageindex )
        {
          return GetPage( pageindex );
        }
      }
      

  14.   

    楼主如果想直接用实体构造访问数据库的command,那么你的实体还不够,你还需要在实体上定义一些自定义特性Attribute(字段名+类型等等信息),然后通过反射实现....否则你就通过继承,由基类重写构造command
      

  15.   

    楼主如果想直接用实体构造访问数据库的command,那么你的实体还不够,你还需要在实体上定义一些自定义特性Attribute(字段名+类型等等信息),然后通过反射实现....否则你就通过继承,由基类重写构造command谢谢 michael_zy(枫林) 的提示.
      

  16.   

    有进步,自已搞了段测试代码:
        public class Class1<T>
        {        public List<T> GetModels()
            {
                List<T> ms = new List<T>();
                T obj;            for (int i = 0; i < 5; i++)
                {
                    obj = (T)Activator.CreateInstance(typeof(T));
                    foreach (PropertyInfo   fi in typeof(T).GetProperties())
                    {
                        if (fi.Name == "Code")
                            fi.SetValue(obj, i.ToString(), null);
                    }
                    ms.Add(obj);
                }
                return ms;
            }
        }测试:        static void Main(string[] args)
            {
                Class1<CompanyModel> cm = new Class1<CompanyModel>();
                List<CompanyModel> lcm = cm.GetModels();            foreach (CompanyModel m in lcm)
                {
                    Console.WriteLine(m.Code  );
                }            
                
                Console.ReadKey();
            }
      

  17.   

    Ivony(授人以鱼不如授人以渔,上海谋生)
    有没有考虑过直接用DataReader?