泛型的基本概念我就不在这重复了,不了解的同学请自行百度。

我主要写下我在项目中要到的泛型实例。献丑了.....有什么不好或不对的地方大家尽可评论留言。

为什么要用泛型?

通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱、拆箱,在一定程度上提升了应用程序的性能。

作为一个想法的程序猿,不能仅仅只会"复制 粘贴"。

代码的封装、重用是可以大大提高你的效率,对于之后代码的修改及二次开发很有帮助。

当然使你"看起来"很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# 泛型使用笔记的更多相关文章

  1. 《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)

    终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是 ...

  2. 【09-03】java泛型学习笔记

    静态方法的泛型 /** * @description 静态方法的泛型无法使用类定义的泛型,因为类在实例化时才确定具体的泛型类,因此静态方法要使用泛型需要使用泛型方法的方式 */ public clas ...

  3. 《C#高级编程(第六版)》泛型学习笔记(一):泛型优点和特性 (转载)

    原文出处:http://www.cnblogs.com/xun126/archive/2011/01/13/1933838.html 泛型是CLR 2.0的一个新特性,在CLR 1.0中,要创建一个灵 ...

  4. Java泛型学习笔记 - (七)浅析泛型中通配符的使用

    一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List< ...

  5. Java泛型学习笔记 - (六)泛型的继承

    在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: Object obj = new Integer(10); 这其实就是面向对象编程中的is ...

  6. Java泛型学习笔记 - (五)泛型接口

    所谓泛型接口, 类似于泛型类, 就是将泛型定义在接口上, 其格式如下: public interface 接口名<类型参数>如: interface Inter<T> { pu ...

  7. Java泛型学习笔记 - (四)有界类型参数

    1. 当我们希望对泛型的类型参数的类型进行限制的时候(好拗口), 我们就应该使用有界类型参数(Bounded Type Parameters). 有界类型参数使用extends关键字后面接上边界类型来 ...

  8. Java泛型学习笔记 - (三)泛型方法

    泛型方法其实和泛型类差不多, 就是把泛型定义在方法上, 格式大概就是: public <类型参数> 返回类型 方法名(泛型类型 变量名) {...}泛型方法又分为动态方法和静态方法,:1. ...

  9. Java泛型学习笔记 - (二)泛型类

    1. 我们先写一个没有泛型的类Box: public class Box { private Object obj; public Box() {} public Object getObj() { ...

  10. Java泛型学习笔记 - (一)泛型的介绍

    一.什么是泛型:泛型的作用是用来规定一个类, 接口或方法所能接受的数据的类型. 就像在声明方法时指定参数一样, 我们在声明一个类, 接口或方法时, 也可以指定其"类型参数", 也就 ...

随机推荐

  1. kolla-ansible 重新部署 ceph 遇到的问题

    问题 TASK [ceph : Fetching Ceph keyrings] ******************************************* fatal: [controll ...

  2. mysql--多表连接查询

    一.多表连接查询 SELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段; 1.交叉连接:不适用任何匹配条件.生成笛卡尔积 sele ...

  3. linux命令之文件备份与压缩命令

    1.tar:打包备份 该命令是将多个命令打包到一起,并且可以实现解压打包.打包是将多个文件或者目录变成一个总的文件,压缩则是将一个大的文件通过压缩算法变成一个小文件. 参数 说明 z(常用) 通过gz ...

  4. java—将查询的结果封装成List<Map>与用回调函数实现数据的动态封装(44)

    手工的开始QueryRunner类.实现数据封装: MapListHandler MapHandler BeanListHandler BeanHandler 第一步:基本的封装测试 写一个类,Que ...

  5. 【12c OCP】CUUG OCP认证071考试原题解析(34)

    34.choose two View the Exhibit and examine the structure of the PRODUCT_INFORMATION and INVENTORIES ...

  6. jquery优化轮播图2

    继续优化 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  7. SQL Server 根据树状结构表生成以/号分割的路由字符串

    很多情况下,我们有必要把树形结构进行数据梳理.比如,要方便的过滤出一个父节点下的所有子节点等等... 这个时候,我们可以生成一个路径表字符串,在应用时只需要对该字符串进行索引即可达成目的. 目标:按图 ...

  8. php-fpm 和 nginx 的两种通信方式

    在 linux 中,nginx 服务器和 php-fpm 可以通过 tcp socket 和 unix socket 两种方式实现. 一下内容转自:https://blog.csdn.net/qq62 ...

  9. flask后端获取前端post/get数据

    post:用request.form 而且要加上return !!记着加上return get:用 request.args()就可以了

  10. [转] Foobar2000 DSP音效外挂元件-Part4

    [转] Foobar2000 DSP音效外挂元件-Part4 在第1部分的文章里主要介绍了foobar2000预设的DSP音效调整,这些则示要介绍几个比较会用到的DSP外挂元件,在foobar2000 ...