C# 通过反射初探ORM框架的实现原理(详解)
作者:cccc_hi 发布时间:2023-08-30 20:05:30
标签:C#,反射,ORM框架
背景:
以前学的Java进行开发,多用到Mybatis,Hiberante等ORM框架,最近需要上手一个C#的项目,由于不是特别难,也不想再去学习C#的ORM框架,所以就想着用反射简单的实现一下ORM框架的内容,简单的增删改查,没有用到多表之间的联系。
反射:
Java和C#中的反射大体相同,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。我的理解就是可以程序运行时动态的获取对象的属性和方法,并且可以进行与之相关的调用。
首先看一下C#中反射实现方式:
获取Type对象,反射操作都需要通过Type对象来进行。
通过全限定名来获取 Type tp = Type.GetType("TJCommon.Dao.Deriver");
通过类来获取 Type tp = typeof(Int)
获取到Type对象后我们可以通过其构造方法来创建对象
调用无参构造
// 获取类的初始化构造信息
ConstructorInfo ct = tp.GetConstructor(System.Type.EmptyTypes);
// 调用不带参数的构造器
T newObj = (T)ct.Invoke(null);
调用有参构造
//定义参数类型数组
Type[] tps = new Type[2];
tps[0] = typeof(int);
tps[1] = typeof(string);
//获取类的初始化参数信息
ConstructorInfo ct2 = tp.GetConstructor(tps);
//定义参数数组
object[] obj = new object[2];
obj[0] = (object)100;
obj[1] = (object)"Param Example";
//调用带参数的构造器
ExampleClass Ex2 = (ExampleClass)ct2.Invoke(obj);
获得所有公共字段
// 获取到所有公共字段
FieldInfo[] arr = t.GetFields();
// 给指定的字段赋值 需要传递进来一个对象 newObj
f.SetValue(newObj, r[name]);
这里就介绍这几个方法,通过反射可以获得类中的所有信息,并且可以进行调用,还可以打破封装(不安全)
练习
下面就是通过反射将从数据库中获取到的结果集自动封装到Bean中。无需手动封装
public static T dataToObj(String str)
{
String strSql = str;
DataSet ds = SqlCompose.ExecuteSqlQuery(strSql);
Type t = typeof(T);
DataRow r = ds.Tables[0].Rows[0]; // 找到一行
FieldInfo[] arr = t.GetFields(); // 返回所有公共字段(public)
ConstructorInfo ct = t.GetConstructor(System.Type.EmptyTypes);
T newObj = (T)ct.Invoke(null);
if (r != null)
{
foreach (FieldInfo f in arr)// 遍历所有字段
{
string name = f.Name;
Type type2 = f.FieldType;
if (r[name].GetType() != typeof(DBNull))
{
string typeName = f.FieldType.Name;
f.SetValue(newObj, r[name]);
}
}
}
else
{
newObj = default(T);
}
ds.Tables.Clear();
return newObj;
}
封装到List
public static List<T> dataToList(String str)
{
List<T> list = new List<T>();
String strSql = str;
DataSet ds = SqlCompose.ExecuteSqlQuery(strSql);
Type t = typeof(T);
FieldInfo[] arr = t.GetFields(); // 返回所有公共字段(public)
ConstructorInfo ct = t.GetConstructor(System.Type.EmptyTypes);
foreach (DataRow dr in ds.Tables[0].Rows)
{
T newObj = (T)ct.Invoke(null);
foreach (FieldInfo f in arr)// 遍历所有字段
{
string name = f.Name;
Type type2 = f.FieldType;
string typeName = f.FieldType.Name;
if (dr[name].GetType() != typeof(DBNull))
{
f.SetValue(newObj, dr[name]);
}
}
list.Add(newObj);
}
ds.Tables.Clear();
return list;
}
拼接字符串进行insert操作
public static void inserByBean(string tableName, T target)
{
StringBuilder sql = new StringBuilder(); // 拼接的sql
sql.Append("insert into "+tableName+"(");
Type t = target.GetType();
PropertyInfo[] ps = t.GetProperties();
for (int i = 0; i < ps.Length; i++)
{
object obj = ps[i].GetValue(target, null);
if (obj != null)
{
string name = ps[i].Name;
if (i != ps.Length - 1)
{
sql.Append(" " + name + ",");
}
else
{
sql.Append(" " + name + "");
}
}
}
sql.Append(") values(");
for (int i = 0; i < ps.Length; i++)
{
object obj = ps[i].GetValue(target, null);
if (obj != null)
{
if (i != ps.Length - 1)
{
if (ps[i].PropertyType == typeof(string) || ps[i].PropertyType == typeof(DateTime))
{
sql.Append("'" + obj + "',");
}
else {
sql.Append("" + obj + ",");
}
}
else
{
if (ps[i].PropertyType == typeof(string) || ps[i].PropertyType == typeof(DateTime))
{
sql.Append("'" + obj + "')");
}
else
{
sql.Append("" + obj + ")");
}
}
}
}
string resultSql = sql.ToString();
SqlCompose.ExecuteSqlNonQuery(resultSql);
}
来源:http://www.cnblogs.com/liyuhui-Z/archive/2017/12/12/8026505.html
0
投稿
猜你喜欢
- 序言:此前,我们主要通过XML来书写SQL和填补对象映射关系。在SpringBoot中我们可以通过注解来快速编写SQL并实现数据访问。(仅需
- 本文实例讲述了Java单例模式。分享给大家供大家参考,具体如下:在实际开发的时候会有一些需求,在某个类中只能允许同时存在一个对象。这时就需要
- 如下所示:class Program {
- 本文实例为大家分享了C#超市收银系统设计的具体代码,供大家参考,具体内容如下1.登录界面代码如下:using System;using Sy
- C#利用缓存分块读写大文件,供大家参考,具体内容如下在日常生活中,可能会遇到大文件的读取,不论是什么格式,按照储存文件的格式读取大文件,就会
- Android 监听手机GPS打开状态实现代码GPS_Presenterpackage com.yiba.core;import andro
- Java中有四种权限修饰符publicprotected(default)private同一个类yesyesyesyes同一个包yesyes
- 基本用法不说了,网上例子很多,这里主要介绍下比较特殊情况下使用的方法。1. 分组有的时候,我们对一个实体类需要有多中验证方式,在不同的情况下
- 本文介绍了java web每天定时执行任务,分享给大家,具体如下:第一步:package com.eh.util;import java.u
- springboot:接收date类型的参数今天有个postmapping方法,地址都正确,就是死活进不去,真是奇怪了。终于从日志中得出些端
- 本文实例为大家分享了java二叉查找树的具体代码,供大家参考,具体内容如下package 查找;import edu.princeton.c
- 我就废话不多说了,大家还是直接看代码吧~package c10; import java.util.Scanner; public clas
- 1.切所有controller下的请求项目结构任意公共方法的执行:execution(public * (…))##public可以省略,
- SpringBoot@DeleteMapping(/xxx/{id})请求报405在学习SpringBoot2.x实现 restful 的d
- 一、代理模式代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机
- 手动将本地jar添加到Maven仓库将jar添加到本地仓库的做法以下面pom.xml依赖的jar包为例:实际项目中pom.xml依赖写法:&
- 最近 IDEA 2020最后一个版本发布了 ,已经内置了Lombok插件,SpringBoot 2.1.x之后的版本也在Starter中内置
- 本文实例为大家分享了java实现简单扫雷游戏的具体代码,供大家参考,具体内容如下package com.test.swing;import
- 前言小小知识,不值一提,了解了也不能让你提高身价,但是不了解你就是比别人少知道点!事儿就是这么个事儿,直接正题吧! 直接看代码演示优先级当方
- 性能优化点:1.使用int不使用double。(单位用分不用元)也省去了还要用math.round四舍五入,把double类型数据只留小数点