对象关系映射,靠纯手打,是个超级繁琐又类的苦力活,即便它能给你再高的运行效率,但是也会损失开发效率。
c#在netframework中其实已经提供了ORM框架了,叫做entity framework,这个框架其实已经做的蛮好的了,但是框架实在是太重,重到写出来的代码在配置不那么好的电脑上跑起来都卡顿。
因此我们决定自己写这么一个框架,一来重在轻量;二来,就是想探探路,看看ORM框架到底是怎么做出来的。
当然,让我自己凭空造楼是做不到的,但是我们可以借鉴,尤其是在互联网这么发达的时代,去github看看别的的开源代码就OK了。
一、反射。
首先我们要解决的就是当从数据库中取出值来了之后,怎么直接赋值给相应的对象的属性的问题,我们记得,传统的做法就是
dt.Rows[i][“ID”]
这么一个一个字段去写,碰到字段比较多的表,那就会打半天了。
反射,就是要获得该类的变量的名称,然后赋值给该变量:
public List<T> ExecSelect<T>(string sqlCmd) where T : new() { List<T> list = new List<T>(); DataTable dt = Select(sqlCmd); if (dt.Rows.Count == 0) { return list; } PropertyInfo[] properties = ReflectionHelper.GetProperties(new T().GetType()); for (int i=0;i<dt.Rows.Count;i++) { T entity = new T(); foreach (PropertyInfo property in properties) { String name = property.Name; ReflectionHelper.SetPropertyValue(entity, property, dt.Rows[i][name]); } list.Add(entity); } return list; }
以上的T就是一种泛型,至于泛型是什么,自行百度。
GetProperties函数即是泛型用于获取类的变量的方法,它有一些参数,包括获取变量为public修饰等等参数:
public static PropertyInfo[] GetProperties(Type type) { return type.GetProperties(BindingFlags.Public | BindingFlags.Instance); }
二、Value.
既然我们已经通过GetProperties获取了该类的属性,那么通过SetValue直接给其赋值就好了,问题是,如果我们从数据库中取出来的值和它不匹配呢,因此我们需要转化Value类型。
if (Convert.IsDBNull(value) || (value == null)) { return null; } string typeName = type.FullName.ToString(); System.Console.WriteLine(typeName); if (type == typeof(System.Nullable<UInt16>)) { value = Convert.ToUInt16(value); } else if (type == typeof(System.Nullable<UInt32>)) { value = Convert.ToUInt32(value); } else if (type == typeof(System.Nullable<UInt64>)) { value = Convert.ToUInt64(value); } else if (type == typeof(System.Nullable<Int32>)) { value = Convert.ToInt32(value); } else if (type == typeof(System.Nullable<Int64>)) { value = Convert.ToInt64(value); } switch (typeName) { case "System.String": if (!isNullOrEmpty(value)) value = value.ToString(); break; case "System.Boolean": if (!isNullOrEmpty(value)) value = Convert.ToBoolean(value); break; case "System.Int16": if (!isNullOrEmpty(value)) value = Convert.ToInt16(value); break; case "System.Int32": if (!isNullOrEmpty(value)) value = Convert.ToInt32(value); break; case "System.Int64": if (!isNullOrEmpty(value)) value = Convert.ToInt64(value); break; case "System.Double": if (!isNullOrEmpty(value)) value = Convert.ToDouble(value); break; case "System.Float": if (!isNullOrEmpty(value)) value = Convert.ToDouble(value); break; case "System.Single": if (!isNullOrEmpty(value)) value = Convert.ToDouble(value); break; case "System.Decimal": if (!isNullOrEmpty(value)) value = Convert.ToDecimal(value); break; case "System.DateTime": if (!isNullOrEmpty(value)) value = Convert.ToDateTime(value); break; } return value; }
三、反射与动态编译。
Reflection真的是个好东西,但是net4.0后会有一个更好的东西:dynamic,要知道反射其实是很费效率的,但是动态编译就会快的多,如果你不理解dynamic,那么以下的例子就会告诉你这两者的区别:
public void test() { SomeClass c = new SomeClass(); PropertyInfo property = c.GetType().GetProperties()[0]; StartTest("begin reflection."); for (int i = 0; i < 1000000; i++) { property.SetValue(c, i, null); } EndTest("end reflection"); IDynamicPropertyInfo dproperty = new DynamicType(c.GetType()).GetProperties()[0]; StartTest("begin dynamic."); for (int i = 0; i < 1000000; i++) { dproperty.SetValue(c, i, null); } EndTest("end dynamic"); }
那么这两者的时间差呢:
—— Test started: Assembly: Pixysoft.Framework.Reflection.dll ——
begin reflection.
end reflection
00:00:09.0625000
begin dynamic.
end dynamic
00:00:00.0468750
差别就太远了,所以如果你觉得因为反射你的程序变慢了,不如试试动态编译。
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
原文链接:http://chaochaoblog.com/archives/3134
吵吵微信朋友圈,请付款实名加入:
受教[鼓掌]
SetPropertyValue 这个方法在哪