The code in c that converts DataTable to a set of entities using delegate reflection

  • 2020-05-07 20:19:29
  • OfStack

Constraints on generics:
 public static class ToModel<T> where T : class, new()

Define delegate:
public delegate void SetString(string value);

Create delegate method:
 
private static SetString CreateStringDelegate(T model, string propertyName) 
{ 
MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod(); 
Type type = typeof(SetString); 
return Delegate.CreateDelegate(type, model, mi) as SetString; 
} 

Convert DataTable to entity set using reflection and delegation:
 
public static IList<T> GetDelegate_ToModelList(DataTable dt) 
{ 
IList<T> list = new List<T>(); 
if (dt == null || dt.Rows.Count < 1) return list; 
SetString setDelegateString; 
foreach (DataRow dr in dt.Rows) 
{ 
T model = new T(); 
foreach (DataColumn dc in dt.Columns) 
{ 
setDelegateString = CreateStringDelegate(model, dc.ColumnName); 
setDelegateString(dr[dc.ColumnName].ToString()); 
} 
list.Add(model); 
} 
return list; 
} 

This is where the problem comes in, because the parameters defined by the delegate are of type string, and because we might have int or DateTime in our entity, then we need to use generic delegates
If the delegate is defined like this:
 public delegate void SetString<PT>(PT value)

Create the delegate method (there is a problem here, do not know how to handle) :
 
private static SetString CreateStringDelegate(T model, string propertyName) 
{ 
MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod(); 
Type type = typeof(model).GetProperty(propertyName).PropertyType; 
return Delegate.CreateDelegate(type, model, mi) as SetString<type>; 
} 

Convert DataTable to entity set using reflection and delegation:
 
public static IList<T> GetDelegate_ToModelList(DataTable dt) 
{ 
IList<T> list = new List<T>(); 
if (dt == null || dt.Rows.Count < 1) return list; 
foreach (DataRow dr in dt.Rows) 
{ 
T model = new T(); 
foreach (DataColumn dc in dt.Columns) 
{ 
SetString<typeof(T).GetProperty(dc.ColumnName).PropertyType> setDelegateString = CreateStringDelegate(model, dc.ColumnName); 
setDelegateString(dr[dc.ColumnName].ToString()); 
} 
list.Add(model); 
} 
return list; 
} 

1 straight doubt, hope someone to help me solve the doubt, direct reflection method I also have, but this problem is not solved, in the mind 1 straight have a pimple, hope someone to help, thank you
Generics can be built dynamically. Once you understand this, you can solve it. Attached is my brief code:
 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 
using System.Reflection; 
namespace RftToModel { 
class Program { 
static void Main(string[] args) { 
var result = ToModel<TestModel>.GetDelegate_ToModelList(BuildSampleTable()); 
foreach (var item in result) { 
Console.WriteLine(item); 
} 
Console.Read(); 
} 
static DataTable BuildSampleTable() { 
DataTable result = new DataTable(); 
result.Columns.Add("ID", typeof(int)); 
result.Columns.Add("Name", typeof(string)); 
result.Columns.Add("IsDeleted", typeof(bool)); 
result.Rows.Add(new object[] { 1, "M.K", false }); 
result.Rows.Add(new object[] { 2, "B.G", true }); 
return result; 
} 
} 
public class TestModel { 
public int ID { get; set; } 
public string Name { get; set; } 
public bool IsDeleted { get; set; } 
public override string ToString() { 
return string.Format("ID:{0} Name:{1} IsDeleted:{2}", ID, Name, IsDeleted); 
} 
} 
public delegate void SetValue<T>(T value); 
public static class ToModel<T> where T : class, new() { 
private static Delegate CreateSetDelegate(T model, string propertyName) { 
MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod(); 
// A generic delegate type is constructed here  
Type delType = typeof(SetValue<>).MakeGenericType(GetPropertyType(propertyName)); 
return Delegate.CreateDelegate(delType, model, mi); 
} 
private static Type GetPropertyType(string propertyName) { 
return typeof(T).GetProperty(propertyName).PropertyType; 
} 
public static IList<T> GetDelegate_ToModelList(DataTable dt) { 
IList<T> list = new List<T>(); 
if (dt == null || dt.Rows.Count < 1) return list; 
Delegate setDelegate; 
foreach (DataRow dr in dt.Rows) { 
T model = new T(); 
foreach (DataColumn dc in dt.Columns) { 
setDelegate = CreateSetDelegate(model, dc.ColumnName); 
// So let's change the type  
setDelegate.DynamicInvoke(Convert.ChangeType(dr[dc.ColumnName], GetPropertyType(dc.ColumnName))); 
} 
list.Add(model); 
} 
return list; 
} 
} 
} 

Thank you. I just modified it. I can convert SqlDataReader and DataTable into it
Did not think of DynamicInvoke this method, is to learn, your code writing level is very clear, see is a kind of enjoyment, to learn from you!

Related articles: