首页 新闻 会员 周边 捐助

利用委托反射将DataTable转换为实体集

0
悬赏园豆:5 [已解决问题] 解决于 2012-04-20 10:53

类泛型的约束:

1 public static class ToModel<T> where T : class, new()

定义委托:

1 public delegate void SetString(string value);

创建委托方法:

1 private static SetString CreateStringDelegate(T model, string propertyName)
2 {
3    MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod();
4    Type type = typeof(SetString);
5    return Delegate.CreateDelegate(type, model, mi) as SetString;
6  }

利用反射和委托将DataTable转换为实体集:

 1         public static IList<T> GetDelegate_ToModelList(DataTable dt)
 2         {
 3             IList<T> list = new List<T>();
 4             if (dt == null || dt.Rows.Count < 1) return list;
 5             SetString setDelegateString;
 6             foreach (DataRow dr in dt.Rows)
 7             {
 8                 T model = new T();
 9                 foreach (DataColumn dc in dt.Columns)
10                 {
11                     setDelegateString = CreateStringDelegate(model, dc.ColumnName);
12                     setDelegateString(dr[dc.ColumnName].ToString());
13                 }
14                 list.Add(model);
15             }
16             return list;
17         }

这样写问题就来了,因为委托定义的参数时string类型的,因为我们实体中可能有int或者DateTime类型的,这时就需要用上泛型委托了

如果这样定义委托:

1 public delegate void SetString<PT>(PT value)

创建委托方法(这里有问题,不知如何处理):

1         private static SetString CreateStringDelegate(T model, string propertyName)
2         {
3             MethodInfo mi = model.GetType().GetProperty(propertyName).GetSetMethod();
4             Type type = typeof(model).GetProperty(propertyName).PropertyType;
5             return Delegate.CreateDelegate(type, model, mi) as SetString<type>;
6         }

利用反射和委托将DataTable转换为实体集:

 1         public static IList<T> GetDelegate_ToModelList(DataTable dt)
 2         {
 3             IList<T> list = new List<T>();
 4             if (dt == null || dt.Rows.Count < 1) return list;
 5             foreach (DataRow dr in dt.Rows)
 6             {
 7                 T model = new T();
 8                 foreach (DataColumn dc in dt.Columns)
 9                 {
10                     SetString<typeof(T).GetProperty(dc.ColumnName).PropertyType> setDelegateString = CreateStringDelegate(model, dc.ColumnName);
11                     setDelegateString(dr[dc.ColumnName].ToString());
12                 }
13                 list.Add(model);
14             }
15             return list;
16         }

一直疑惑着,希望有人帮我解决疑惑,直接反射的方法我也有,但是这个问题不解决,心里一直有疙瘩,希望有人帮帮忙,谢谢!

xu_happy_you的主页 xu_happy_you | 菜鸟二级 | 园豆:222
提问于:2012-04-19 16:03
< >
分享
最佳答案
0

泛型可以动态构建的,你了解了这个,就能解决了,附上我的简略代码:

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();
            //这里构造泛型委托类型
            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);
                    //这里改变类型
                    setDelegate.DynamicInvoke(Convert.ChangeType(dr[dc.ColumnName], GetPropertyType(dc.ColumnName)));
                }
                list.Add(model);
            }
            return list;
        }
    }

}

 

希望可以帮助到你。

收获园豆:5
Sun.M | 菜鸟二级 |园豆:333 | 2012-04-20 10:12

谢谢,我刚修改了,我传进去SqlDataReader和DataTable都可以转换了,当时只想着每次返回一个特定类型等委托都不知道如何下手,看着你的方法解决了

没想到DynamicInvoke这个方法,算是学习了,你的代码写着层次好清晰,看了是一种享受,向你学习啊!

xu_happy_you | 园豆:222 (菜鸟二级) | 2012-04-20 10:52
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册