65.9K
CodeProject 正在变化。 阅读更多。
Home

GridView ObjectDataSource 适配器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (6投票s)

2007年2月2日

3分钟阅读

viewsIcon

59894

downloadIcon

333

在这篇简短的文章中,作者提到了两种技术,他使用这两种技术来允许将 GridView 映射到基于现有中间层对象构建的 DataTables。

引言

ASP.NET 2.0 中的 GridView 控件是一个非常强大的控件,我特别喜欢我们可以将 GridView 控件映射到对象数据源的方式。此外,我喜欢 GridView 如何在不需要代码的情况下启用排序和分页。非常好!将 GridView 映射到对象数据源的一个好处(在我看来)是它促进了分层架构。但是,如果您将 GridView 映射到对象数据源,您可能会在尝试对 GridView 进行排序时遇到以下异常

The data source 'objDataSource' does not support sorting 
with IEnumerable data. Automatic sorting is only supported 
with DataView, DataTable, and DataSet

现在,通过选择将 GridView 直接映射到 DataSet 而不是相关的应用程序对象,从而失去将数据封装在中间层对象中的所有巨大好处,这对我来说似乎有点荒谬。所有这些妥协,只是为了让排序可以在 GridView 中工作。在这篇简短的文章中,我想提到两种技术,我使用这两种技术来允许将 GridView 映射到基于现有中间层对象构建的 DataTable。我倾向于将此视为伪适配器模式,它将我的模型对象转换为 DataTable。这样做的好处是,我可以利用我之前编写的所有中间层逻辑,同时还可以实现 GridView 控件的强大功能,例如排序。这两种技术是

  1. 使用反射初始化中间层“模型”层对象。
  2. 使用反射将中间层“模型”层对象转换为 DataTable

在进入代码之前,我应该提到我的应用程序中通常存在的层。这将更容易概念化我在哪里采用上述技术。

  1. 模型层 – 此层包含封装数据的对象。此层由所有轻量级可序列化类组成,这些类仅声明属性。此层中没有任何方法。这些类用于通过应用程序的各个层传递数据。
  2. 控制器层 – 此层是我的 ASP.NET 应用程序和业务逻辑层之间的粘合剂。
  3. 业务逻辑层 – 业务逻辑层作用于模型层中的数据。此层还通过“要求”数据层对模型层对象执行 CRUD(创建、检索、更新和删除)操作来与数据逻辑层进行交互。
  4. 数据逻辑层 – 此层用于对模型层对象执行实际的 CRUD 操作。

我使用的第一种技术是在数据逻辑层中。一旦我从数据库中检索到 DataSet,我就使用反射创建并初始化相关的模型层类。本质上,此方法遍历 DataSet 中一行的所有列,并在我的模型对象中调用相关的 set 方法。只有当我的模型对象具有与 DataSet 中列名匹配的属性名称时,才会发生调用。此方法的结果是初始化的模型层对象。

Public Function InitializeFromDataRow(ByVal aDataRow _
       As System.Data.DataRow, ByVal aType _
       As System.Type) As Object
       Implements IDLL.IBaseDataObject.InitializeFromDataRow
    Try
        Dim props As PropertyInfo()
        Dim myObject As Object
        ' Create our object through reflection
        myObject = Activator.CreateInstance(aType)
        Dim p As PropertyInfo
        props = aType.GetProperties()
        'Now go set all the public attributes based 
        'on the columns and values within the datatable
        For Each p In props
               Dim params(0) As Object
               'Make sure we have a column in dataset 
               'for the attribute we are trying to set.
               If aDataRow.Table.Columns.Contains(p.Name) = True Then
                   params(0) = aDataRow.Item(p.Name)
                   p.GetSetMethod.Invoke(myObject, params)
               End If
        Next
        Return myObject
    Catch ex As Exception
        Throw ex
    End Try
    Return Nothing    
End Function

我使用的第二种技术是在控制器层中。简单地说,在控制器层中放置一个类,该类要求业务逻辑层将模型层对象转换为 DataTable。这使我能够以一种间接的方式将我的 GridView 映射到我的模型对象。我说间接的方式是因为我真正做的只是获取一个模型层对象并将其转换为 DataTable。这就是适配器模式发挥作用的地方。

Public Function ConvertToDataTable(ByVal list As _
       System.Collections.IList, _
       ByVal aType As System.Type) As DataTable
    Try
        Dim aDataTable As New DataTable       
        Dim props As PropertyInfo()
        Dim p As PropertyInfo
        props = aType.GetProperties()
        Dim anObject As Object
        'Create all the pertinent columns
        For Each p In props
            aDataTable.Columns.Add(New _
                 DataColumn(p.Name, p.PropertyType))
        Next
        'Now go add all the data into datatable.
        For Each anObject In list
           Dim row(props.Length - 1) As Object
           Dim i As Integer
           i = 0
           row(props.Length - 1) = New Object()
           For Each p In props
                   row(i) = p.GetValue(anObject, Nothing)
                   i = i + 1
           Next
           aDataTable.Rows.Add(row)
        Next
        Return aDataTable
    Catch ex As Exception
        Throw ex
    End Try
        Return Nothing    
End Function

摘要

使这成为可能的是反射。我附上了一个非常简单的 Web 应用程序,它使用了上面讨论的两种技术。请注意,在附加的源代码中,第一个网格在排序时会导致异常,而第二个网格像魅力一样工作。示例中规避异常的关键代码行是

Return myObject.ConvertToDataTable(myEmployees, _
                GetType(IModelLayer.IEmployee))

这将返回 Employee 模型对象的 DataTable 表示,我的 GridView 可以很好地使用它。

联系作者:Brian Rush

© . All rights reserved.