2012-04-10 10 views
4

私はVS 2010(.Net 4.0)でEF 4.3.1を使用して、データベースから複数の参照テーブルをロードし、 WinFormsアプリケーション。強くReflection .GetValue()オブジェクトを汎用DbSetにキャスト

フォームのロード時に、ローカルに格納されるようにデータをプリフェッチしています。ローカルデータをコントロールにバインドするために使用できる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として機能しません()の代わりに(Tの)DbSetのオブジェクトを返します。私はまた、リフレクションを通して型を知っていても、オブジェクトを適切な型のDbSetにキャストできません。

私はC#Dynamic型にアクセスすることはできませんが、リフレクションとジェネリックスを混在させるのは難しいことですが、反射DbSetを関数に渡すことができる解決策がありますか?おそらく何かMethod.Invokeを使用して?

答えて

1

私はそれを解決したと思うし、解決策はMethod.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 

db.ProvinceStates.ValidateBinding 

ComboBox1.DataSource = db.Cities.GetBinding 

第二に、私は次のように書くことGetMethod、MakeGenericMethod、および呼び出しを使用しました

これは2つの鳥を1つの石で殺し、66のすべてのテーブルのデータをロードし、コントロールをバインドするBindingSourceオブジェクトを作成します。 (DbSetExtenderは私の独自のモジュールで、拡張メソッドを入れていますが、DbExtensionsは.Netフレームワークの一部です)

関連する問題