.NET – strongly convert a reflection .getValue () object to generic DBSET

I am using EF 4.3.1 in VS 2010 (.Net 4.0) to load a large number of reference tables from the database in order to bind them to controls in a WinForms application.

< /p>

When the form loads, I get the data in advance so that it is stored locally, I am creating a dictionary of BindingSource objects, I can use it to bind local data to the control. The purpose is to minimize EF self-validation The impact on cold queries to load forms faster and improve UI responsiveness.

I wrote code to create and obtain BindingSource objects for a given DbSet collection, as shown below:

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< br /> ValidateBinding(Of T)(DbCollection)
Return _dictBindings(DbCollection.[GetType]().GetGenericArguments(0).Name)
End Function

It works, I can call

ValidateBinding(Db.ProvinceStates)

either

ComboBox1. DataSource = GetBinding(Db.Cities)

However, I want to call ValidateBinding on all DbSet collections in the model at startup, and I want to use reflection to iterate the available collections in the context because we are currently Load 66 tables and you can add more tables later.

I wrote the following code:

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

…But it can’t be used as propSet.GetValue() to return an Object instead of DbSet(T). I can’t cast the object to a DbSet of the appropriate type, even if I know the type through reflection.

Cannot access C#Dynamic types, I know it is a pain to mix generics with reflection, but is there a solution to pass the reflected DbSet to my function? Maybe something that uses Method.Invoke?

I think I have solved it, the solution is to use Method.Invoke.

First, I converted my function into an extension method. Although this is not necessary, it allows me to write:

db.ProvinceStates.ValidateBinding 

and

ComboBox1.DataSource = db.Cities.GetBinding

Secondly, I use GetMethod, MakeGenericMethod and Invoke to write the following:

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
methodValidateB inding.Invoke(Nothing, (oSet))
End If
Next

This will kill two birds with one stone, and load data for all 66 tables, and create a BindingSource object to bind the control To. (DbSetExtender is my own extension method module, and DbExtensions is part of the .Net framework.)

I am using EF 4.3 in VS 2010 (.Net 4.0) .1 Load a large number of reference tables from the database in order to bind them to the controls in the WinForms application.

When the form loads, I pre-fetch the data so that it is stored locally, I am creating A dictionary of BindingSource objects that I can use to bind local data to controls. The purpose is to minimize the impact of EF self-verification on cold queries, so as to load forms faster and improve UI responsiveness.

I wrote code to create and obtain BindingSource objects for a given DbSet collection, as follows:

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

This code is valid, I can Call

ValidateBinding(Db.ProvinceStates)

either

ComboBox1.DataSource = GetBinding( Db.Cities)

However, I want to call ValidateBinding on all DbSet collections in the model at startup, and I want to use reflection to iterate the available collections in the context, because we are currently loading 66 tables And you can add more tables later.

I wrote the following code:

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

...but it cannot Used as propSet.GetValue() to return an Object instead of DbSet(T). I also can’t cast the object to a DbSet of the appropriate type, even if I know the type through reflection.

I can’t access C# Dynamic type, I know that mixing generics and reflection is a pain, but is there a solution to pass the reflected DbSet to my function? Maybe something that uses Method.Invoke?

I think I have solved it, the solution is to use Method.Invoke.

First, I will my function Converted to an extension method. Although this is not required, it allows me to write:

db.ProvinceStates.ValidateBinding

and

ComboBox1.DataSource = db.Cities.GetBinding

Secondly, I use GetMethod, MakeGenericMethod and Invoke to write the following:

< pre>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

This will kill two birds with one stone, and load data for all 66 tables, and create a BindingSource object to bind the control to. (DbSetExtender is my own extension method module, and DbExtensions is part of the .Net framework.)

Leave a Comment

Your email address will not be published.