使用泛型轻松填充实例的方法






3.13/5 (16投票s)
使用泛型简化数据访问层的示例。
 
 
引言
随着 2.0 Framework 中泛型的引入,开发者拥有了一种彻底改变开发方式的工具。使用泛型的主要优势包括:
- 类型安全
- IntelliSense 支持
- 减少重复代码
- 包含强大功能的集合(Collections、List、Queue、Stack、LinkedList)
背景
在几乎所有应用程序中,都需要持久化对象实例的状态,以便稍后进行查询和重新生成这些实例。这个重新生成过程通常需要大量的代码、非类型化的集合,从而导致容易出错的代码和较低的性能。在这个简化的数据访问层示例中,我们将看到仅使用两个泛型方法就可以获得任何实体的实例或实例列表。
泛型方法
填充单个实例
/// <SUMMARY>
/// Populates an instance of the entity.
/// </SUMMARY>
/// <PARAM name="entity">The instance of the entity to populate.</PARAM>
/// <PARAM name="record">The current Datareader record.</PARAM>
public static void PopulateEntity<T>(T entity, IDataRecord record)
{
    if (record != null && record.FieldCount > 0)
    {
        Type type = entity.GetType();
        for (int i = 0; i < record.FieldCount; i++)
        {
            if (DBNull.Value != record[i])
            {
                PropertyInfo property = 
                   type.GetProperty(record.GetName(i), 
                   BindingFlags.IgnoreCase | 
                   BindingFlags.Public | BindingFlags.Instance);
                if (property != null)
                {
                    property.SetValue(entity, 
                           record[property.Name], null);
                }
            }
        }
    }
}
填充实例 List
/// <SUMMARY>
/// Populates a List of entities of type T.
/// </SUMMARY>
/// <PARAM name="dr">The DataReader with data of entities.</PARAM>
/// <RETURNS></RETURNS>
public static List<T> PopulateEntities<T>(IDataReader dr)
{
    List<T> entities = new List<T>();
    while (dr.Read())
    {
        T ent = Activator.CreateInstance<T>();
        PopulateEntity<T>(ent, dr);
        entities.Add(ent);
    }
    return entities;
}
使用这些方法
如果需要一个实体的单个实例,请调用方法 PopulateEntity,并将实体类型、一个空实例和 Datareader 的记录作为参数传递。
public static Contact getContactById(int id)
{
    Contact contact = new Contact();
    Database db = DatabaseFactory.CreateDatabase();
    DbCommand dbCommand = db.GetStoredProcCommand("ContactById");
    db.AddInParameter(dbCommand, "contactId", DbType.Int32, id);
    IDataReader idr = db.ExecuteReader(dbCommand);
    if (idr.Read())
    {
        EntityUtils.PopulateEntity<Contact>(contact, idr);
    }
    return contact;
}
如果需要一个实体的实例集合,请调用方法 PopulateEntities,并将实体类型和 Datareader 作为参数传递。
public static List<Contact> getContacts()
{
    Database db = DatabaseFactory.CreateDatabase();
    DbCommand dbCommand = db.GetStoredProcCommand("ContactGetAll");
    IDataReader idr = db.ExecuteReader(dbCommand);
    return (EntityUtils.PopulateEntities<Contact>(idr));
}
使用泛型 List 作为 PopulateEntities 的返回值,我们获得了一个包含强大功能的集合,可以在业务和用户界面层中进行排序、查找、迭代和管理。
配置示例项目
该示例使用 SQL Server 2005 中包含的 AdventureWorks 数据库。修改 web.config 中的连接字符串 LocalSqlServer,并运行位于 App_Data 目录中的 StoredProcedures.sql 脚本以添加必要的存储过程。
结论
泛型在 Framework 中的引入,为这个工具带来了成熟度和生产力的飞跃。因此,我认为这是需要深入了解的一个方面,否则我们将失去一种简单而有利的开发方式。
历史
- 2006 年 12 月 20 日:初始发布
关于 Martín Olivares
我是一名拥有 8 年经验的系统工程师,在企业项目解决方案中担任开发人员/架构师。我一直使用 Microsoft 平台和技术,例如 VB、SQL Server、.NET、MSF。


