c#で委託反射によりDataTableをソリッドセットに変換するコード

5316 ワード

クラス汎用制約:

   public static class ToModel where T : class, new() 
 

委任の定義:

   public delegate void SetString(string value); 
 

委任メソッドの作成:
 
  
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;
}

反射と委任を使用して、DataTableをエンティティセットに変換します.
 
  
public static IList GetDelegate_ToModelList(DataTable dt)
{
IList list = new List();
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;
}

このように問題を書くのは、定義されたパラメータを依頼するときにstringタイプがあるため、私たちのエンティティにintやDateTimeタイプがある可能性があるため、汎用的な依頼が必要です.
委任を定義する場合は、次の手順に従います.

   public delegate void SetString(PT value) 
 

委任メソッドの作成(ここで問題があり、どのように処理するか分かりません):
 
  
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;
}

反射と委任を使用して、DataTableをエンティティセットに変換します.
 
  
public static IList GetDelegate_ToModelList(DataTable dt)
{
IList list = new List();
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 setDelegateString = CreateStringDelegate(model, dc.ColumnName);
setDelegateString(dr[dc.ColumnName].ToString());
}
list.Add(model);
}
return list;
}

ずっと疑問に思って、誰かが私に疑問を解決してくれることを望んで、直接反射する方法は私もありますが、この問題は解決しないで、心の中はずっとしこりがあって、誰かが助けてくれることを望んで、ありがとうございます
汎用型は動的に構築できます.これを理解すれば、解決できます.私の簡略コードを添付します.
 
  
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.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 value);
public static class ToModel where T : class, new() {
private static Delegate CreateSetDelegate(T model, string propertyName) {
MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod();
//
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 GetDelegate_ToModelList(DataTable dt) {
IList list = new List();
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);
//
setDelegate.DynamicInvoke(Convert.ChangeType(dr[dc.ColumnName], GetPropertyType(dc.ColumnName)));
}
list.Add(model);
}
return list;
}
}
}

ありがとうございます、私はちょうど改正して、私はSqlDataReaderとDataTableに伝わってすべて変換することができて、その時ただ1つの特定のタイプなどの依頼を返すたびにすべてどのように手をつけるか分からないと思って、あなたの方法を見て解決しました
まさかDynamicInvokeという方法は、勉強になりました.あなたのコードは階層がはっきり書いてあります.見たのは楽しみです.あなたに勉強しましょう.