.net – 强烈地将一个反射.GetValue()对象强制转换为泛型DbSet

我在VS 2010(.Net 4.0)中使用EF 4.3.1从数据库加载大量参考表,以便将它们绑定到WinForms应用程序中的控件.

在表单加载时,我预先获取数据以便它存储在本地,我正在创建一个BindingSource对象的字典,我可以使用它来将本地数据绑定到控件.目的是最小化EF自我验证对冷查询的影响,以便更快地加载表单并提高UI响应能力.

我编写了代码来为给定的DbSet集合创建和获取BindingSource对象,如下所示:

Private _dictBindings As New Dictionary(Of String,BindingSource)

Private Sub ValidateBinding(Of T As Class)(ByRef DbCollection As DbSet(Of T))
   Dim strClassName As String = DbCollection.[GetType]().GetGenericArguments(0).Name
   If Not _dictBindings.ContainsKey(strClassName) Then
      _dictBindings.Add(strClassName,New BindingSource With {.DataSource = DbCollection.Local.ToBindingList})
   End If
End Sub

Public Function GetBinding(Of T As Class)(ByRef DbCollection As DbSet(Of T)) As BindingSource
   ValidateBinding(Of T)(DbCollection)
   Return _dictBindings(DbCollection.[GetType]().GetGenericArguments(0).Name)
End Function

这段代码有效,我可以打电话

ValidateBinding(Db.ProvinceStates)

要么

ComboBox1.DataSource = GetBinding(Db.Cities)

但是,我想在启动时在模型中的所有DbSet集合上调用ValidateBinding,并且我想使用反射来迭代上下文中的可用集合,因为我们当前正在加载66个表并且可以稍后添加更多表.

我写了以下代码:

For Each propSet As PropertyInfo In Db.GetType.GetProperties(BindingFlags.Instance Or BindingFlags.Public).Where(Function(P) P.PropertyType.IsGenericType)
    ValidateBinding(propSet.GetValue(Db,Nothing))
Next

…但它不能用作propSet.GetValue()返回一个Object而不是DbSet(T).我也无法将对象强制转换为适当类型的DbSet,即使我通过反射知道了类型.

我无法访问C#Dynamic类型,我知道将泛型与反射混合是一种痛苦,但有没有一种解决方案可以将反射的DbSet传递给我的函数?也许是使用Method.Invoke的东西?

解决方法

我想我已经解决了,解决方案是使用Method.Invoke.

首先,我将我的函数转换为扩展方法.虽然这不是必需的,但它允许我写:

db.ProvinceStates.ValidateBinding

ComboBox1.DataSource = db.Cities.GetBinding

其次,我使用GetMethod,MakeGenericMethod和Invoke来编写以下内容:

Dim methodLoad = GetType(DbExtensions).GetMethod("Load",BindingFlags.Static Or BindingFlags.Public)

For Each propSet As PropertyInfo In Db.GetType.GetProperties(BindingFlags.Instance Or BindingFlags.Public).Where(Function(P) P.PropertyType.IsGenericType)
   Dim oSet As Object = propSet.GetValue(Db,Nothing)
   methodLoad.Invoke(Nothing,{oSet})

   Dim methodValidateBinding = GetType(DbSetExtender).GetMethod("ValidateBinding",BindingFlags.Static Or BindingFlags.Public).MakeGenericMethod(propSet.PropertyType.GetGenericArguments(0))
   If methodValidateBinding IsNot Nothing Then
      methodValidateBinding.Invoke(Nothing,{oSet})
   End If
Next

这会一举两得,并为所有66个表加载数据,并创建BindingSource对象以将控件绑定到. (DbSetExtender是我自己的扩展方法模块,而DbExtensions是.Net框架的一部分.)

相关文章

Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强...
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办...
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace...
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用...
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选...
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As Dat...