C# 泛型使用笔记
泛型的基本概念我就不在这重复了,不了解的同学请自行百度。
我主要写下我在项目中要到的泛型实例。献丑了.....有什么不好或不对的地方大家尽可评论留言。
为什么要用泛型?
通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱、拆箱,在一定程度上提升了应用程序的性能。
作为一个想法的程序猿,不能仅仅只会"复制 粘贴"。
代码的封装、重用是可以大大提高你的效率,对于之后代码的修改及二次开发很有帮助。
当然使你"看起来"很NB,增加自己的成就感。
使用泛型实例
我在项目用到泛型的地方主要是用在封装获取数据的时候。
之前获取一个Model PR_Form 的数据我是这样写的。
public partial class PR_Form
{
public PR_Form()
{}
public long FM_ID {get;set;}
public string PR_NO {get;set;}
}
//根据FM_ID获取PR_Form数据
public PR_Form GetPRForms(long FM_ID)
{
//构造 where条件
string searchCriteria = "where FM_ID=@FM_ID";
//参数
SqlParameter[] sqlParams = { new SqlParameter("@FM_ID", FM_ID) };
PR_Form _form = new PR_Form();
//拼接sql语句
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append(@"select [FM_ID],
[PR_NO] from PR_Form ");
sqlBuilder.Append(searchCriteria);
//查询数据 注:这里用dataset不是很好,哈哈
DataSet ds = DbHelperSQL.Query(sqlBuilder.ToString(), sqlParams);
//如果查到数据给_form 赋值
if (ds.Tables[].Rows.Count > )
{
//将记录映射为实例
for (int i = ; i < ds.Tables[].Rows.Count; i++)
{
if (null != ds.Tables[].Rows[i]["FM_ID"])
{
_form.FM_ID = long.Parse(ds.Tables[].Rows[i]["FM_ID"].ToString());
} if (null != ds.Tables[].Rows[i]["PR_NO"])
{
_form.PR_NO = ds.Tables[].Rows[i]["PR_NO"].ToString();
}
}
} return _form;
}
上面代码可以优化的地方很多。
首先我这边去掉了很多 PR_Form 属性,实际应用中PR_Form 的数据不止这几个。
那么我每次在读取到数据的时候 “ 将记录映射为实例”是不是可以封装一下?方便之后重用?
当然可以
我们封装一个通用的 DataRow返回相应类的方法
// 将记录映射为实例
private T ConvertToModel<T>(DataRow dr) where T : class, new()//泛型的约束。class:使用此方法的必须是一个类,new():必须有空参数的构造函数
{
T o = new T();
//获取指定类型的公共属性
PropertyInfo[] propertys = o.GetType().GetProperties();
foreach (PropertyInfo p in propertys)
{
try
{
// 判断此属性是否有Setter
if (!p.CanWrite)
continue; object value = dr[p.Name];
if (value != DBNull.Value)
p.SetValue(o, dr[p.Name], null); }
catch{}
} return o;
}
然后我们的代码就变成这样了。
//根据FM_ID获取PR_Form数据
public PR_Form GetPRForms(long FM_ID)
{
//构造 where条件
string searchCriteria = "where FM_ID=@FM_ID";
//参数
SqlParameter[] sqlParams = { new SqlParameter("@FM_ID", FM_ID) };
PR_Form _form = new PR_Form();
//拼接sql语句
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append(@"select [FM_ID],
[PR_NO]
from PR_Form ");
sqlBuilder.Append(searchCriteria);
//查询数据 注:这里用dataset不是很好,哈哈
DataSet ds = DbHelperSQL.Query(sqlBuilder.ToString(), sqlParams);
//如果查到数据给_form 复制
if (ds.Tables[].Rows.Count > )
{
_form = ConvertToModel(ds.Tables[].Rows[]);
} return _form;
}
博主:这样写之后我们不管 DataRow增加任何列都不用修改代码。
博友:博主你在扯淡么? DataRow的列都是sql语句决定,如果数据库增加列,我还是要修改Model,和sql查询语句!
博主:哈哈,是这样的。那我们继续封装.....接下来我们通过类的属性封装一下查询语句。
博友:别别别。。。一步到位可以么? 如果我要查询其他Model的数据呢?这个也一起封装了岂不是更好?
博主:OK。长话短说
既然我们要通过类来生成Sql语句,那就要对Model类进行一些配置,比如说类对应的表名、表的主键、要查询的字段等。。。
我们根据相应的配置来生成sql语句。
首先我们要对model 类进行修改。给model类添加自定义属性
[Table(TableName = "PR_Form", PrimaryKey = "FM_ID ", SortType = , SearchFields = "*")]
//TableName:表示对应数据库的表名,PrimaryKey:表示表的主键,SearchFields:查询字段(如id,name....),我这里省事直接写了*
public partial class PR_Form
{
public PR_Form()
{}
public long FM_ID {get;set;}
public string PR_NO {get;set;}
}
添加接收自定义属性的类TableAttribute
/// <summary>
/// 数据库表属性
/// </summary>
public class TableAttribute : Attribute
{
public TableAttribute()
{
} /// <summary>
/// 实例化
/// </summary>
/// <param name="tablename">表名或视图名 视图名要有对应类存在</param>
public TableAttribute(string tablename)
{
_tablename = tablename;
} /// <summary>
/// 实例化
/// </summary>
/// <param name="tablename">表名或视图名 视图名要有对应类存在</param>
/// <param name="primaryKey">主键 默认值:Id</param>
public TableAttribute(string tablename, string primaryKey)
{
_tablename = tablename;
_primaryKey = primaryKey;
} private string _primaryKey = "Id";
/// <summary>
/// 主键 默认值:Id
/// </summary>
public string PrimaryKey { get { return _primaryKey; } set { _primaryKey = value; } } private string _tablename = "";
/// <summary>
/// 表名或视图名 视图名要有对应类存在
/// </summary>
public string TableName { get { return _tablename; } set { _tablename = value; } } private int _sortType = ;
/// <summary>
/// 排序类型 查询时用到 默认值:-1(默认排序), 0(ASC) ,1(DESC)
/// </summary>
public int SortType { get { return _sortType; } set { _sortType = value; } } private string _sortFields = "Id";
/// <summary>
/// 排序字段 查询时用到 SortType>0时生效 默认值:Id
/// </summary>
public string SortFields { get { return _sortFields; } set { _sortFields = value; } } private string _SearchFields = "*";
/// <summary>
/// SearchFileds 查询时用到 默认值:*
/// </summary>
public string SearchFields { get { return _SearchFields; } set { _SearchFields = value; } } private int _Top = ;
/// <summary>
/// Top多少数据 查询时用到 默认值:0 无限制
/// </summary>
public int Top { get { return _Top; } set { _Top = value; } } private string _ConnectionString = "ConnectionString";
/// <summary>
/// 连接字符串 默认为:ConnectionString
/// </summary>
public string ConnectionString { get { return _ConnectionString; } set { _ConnectionString = value; } } }
获取model PR_Form的自定义属性这样写。
object[] objAttrs = new PR_Form().GetType().GetCustomAttributes(typeof(TableAttribute), true);
OK,准备工作就绪。
最后结果
public T GetModel<T>(long FM_ID) where T : class, new()
{
T obj = new T();
//获取 Model 配置
object[] objAttrs = new T().GetType().GetCustomAttributes(typeof(TableAttribute), true);
if (objAttrs.Length > )
{
TableAttribute attr = objAttrs[] as TableAttribute;
if (attr != null)
{
//参数
SqlParameter[] sqlParams = { new SqlParameter("@FM_ID", FM_ID) };
//构造 sql条件
string strSQL = "select {0} from {1} where {2}=@FM_ID" ";
strSQL = string.Format(strSQL, attr.SearchFields, attr.TableName, attr.PrimaryKey); //查询数据 注:这里用dataset不是很好,哈哈
DataSet ds = DbHelperSQL.Query(strSQL, sqlParams);
if (ds.Tables[] == null || ds.Tables[].Rows.Count < )
return null;
//将记录映射为实例
obj=ConvertToModel<T>(dt.Rows[]); return obj;
}
}
return null; }
调用代码
var _Form= bllbase.GetModel<PR_Form>( FormId);
献丑了。这是我第一次在项目中使用泛型,大神莫笑我啊。
那里不对的地方,请打加指出。
C# 泛型使用笔记的更多相关文章
- 《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)
终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是 ...
- 【09-03】java泛型学习笔记
静态方法的泛型 /** * @description 静态方法的泛型无法使用类定义的泛型,因为类在实例化时才确定具体的泛型类,因此静态方法要使用泛型需要使用泛型方法的方式 */ public clas ...
- 《C#高级编程(第六版)》泛型学习笔记(一):泛型优点和特性 (转载)
原文出处:http://www.cnblogs.com/xun126/archive/2011/01/13/1933838.html 泛型是CLR 2.0的一个新特性,在CLR 1.0中,要创建一个灵 ...
- Java泛型学习笔记 - (七)浅析泛型中通配符的使用
一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List< ...
- Java泛型学习笔记 - (六)泛型的继承
在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: Object obj = new Integer(10); 这其实就是面向对象编程中的is ...
- Java泛型学习笔记 - (五)泛型接口
所谓泛型接口, 类似于泛型类, 就是将泛型定义在接口上, 其格式如下: public interface 接口名<类型参数>如: interface Inter<T> { pu ...
- Java泛型学习笔记 - (四)有界类型参数
1. 当我们希望对泛型的类型参数的类型进行限制的时候(好拗口), 我们就应该使用有界类型参数(Bounded Type Parameters). 有界类型参数使用extends关键字后面接上边界类型来 ...
- Java泛型学习笔记 - (三)泛型方法
泛型方法其实和泛型类差不多, 就是把泛型定义在方法上, 格式大概就是: public <类型参数> 返回类型 方法名(泛型类型 变量名) {...}泛型方法又分为动态方法和静态方法,:1. ...
- Java泛型学习笔记 - (二)泛型类
1. 我们先写一个没有泛型的类Box: public class Box { private Object obj; public Box() {} public Object getObj() { ...
- Java泛型学习笔记 - (一)泛型的介绍
一.什么是泛型:泛型的作用是用来规定一个类, 接口或方法所能接受的数据的类型. 就像在声明方法时指定参数一样, 我们在声明一个类, 接口或方法时, 也可以指定其"类型参数", 也就 ...
随机推荐
- mysql--对行(表中数据)的增删改查
一.插入数据(增加)insert 1.插入数据(顺序插入) 语法一: INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n); #指定字段来插入数据,插 ...
- Java50道经典习题-程序10 自由落体
题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半:再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? import java.util.Scanner; public cl ...
- 自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 (转载)
自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 转自:https://www.cnblogs.com/ailiailan/p/8304989.html 作为测试, ...
- jquery分页插件pagination
参考1:https://www.cnblogs.com/jingping/p/3925976.html 参考2:https://segmentfault.com/a/1190000014487357 ...
- Creating a custom analyzer in ElasticSearch Nest client
Creating a custom analyzer in ElasticSearch Nest client Question: Im very very new to elasticsearch ...
- java使用Redis8--3.0集群
Redis集群至少需要3个主节点 # cd /usr/redis 创建一个目录 # mkdir cluster # cd cluster 1.复制一个配置文件 # cp ../redis.conf 9 ...
- angular核心原理解析2:注入器的创建和使用
上一课没有讲到创建注入器的方法createInjector. 此方法,会创建两种不同的注入器:第一种叫做providerInjector,第二种叫做instanceInjector.providerI ...
- [Objective-C语言教程]类型定义:typedef(19)
Objective-C编程语言提供了一个名称为typedef的关键字,可以使用此关键字为类型指定新名称. 以下是为单字节数字定义术语BYTE的示例 - typedef unsigned char BY ...
- linux上搭建nginx+php+mysql环境详细讲解
1.mysql安装 #安装编译环境 yum install -y gcc gcc-c++ gcc-devel g++ g++-devel; yum install -y wget yum instal ...
- 「PKUWC2018」Slay the Spire
题目链接 题意分析 这个题其实不是期望 就是一共有\(C_{2n}^m\)种情况 每一种情况选择\(k\)张牌 然后求最大攻击值的总和 我们考虑 当前抽出了选出了\(i\)张强化牌 \(m-i\)张攻 ...