4

VS 2010(.Net 4.0)でEF 4.3.1を使用して、データベースから多数の参照テーブルをロードし、それらをWinFormsアプリのコントロールにバインドしています。

フォームの読み込み時に、ローカルに保存されるようにデータをプリフェッチし、ローカルデータをコントロールにバインドするために使用できるBindingSourceオブジェクトのディクショナリを作成しています。目的は、フォームの読み込みを高速化し、UIの応答性を向上させるために、コールドクエリに対するEFの自己検証の影響を最小限に抑えることです。

次のように、特定の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()がDbSet(of T)ではなくObjectを返すため、機能しません。また、リフレクションでタイプがわかっていても、オブジェクトを適切なタイプのDbSetにキャストできません。

C#Dynamicタイプにアクセスできず、ジェネリックスとリフレクションを組み合わせるのは面倒ですが、リフレクトされたDbSetを関数に渡すことができるソリューションはありますか?おそらくMethod.Invokeを使用したものですか?

4

1 に答える 1

1

私はそれを解決したと思います。解決策は 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 フレームワークの一部です。)

于 2012-04-11T07:27:16.400 に答える