泛型(Generics) (整理自张子阳博客MSDN等)
泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。泛型将类型参数的概念引入.NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险.
机制:
C#泛型代码在被编译为IL代码和无数据时,采用特殊的占位符来表示泛型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以"on-demand"的方式,发生在JIT编译时。
C#泛型能力由CLR在运行时支持,区别于C++的编译时模板机制,这使得泛型能力可以在各个支持CLR的语言之间进行无缝的互操作。
public class SortHelper<T> whereT:IComparable {
// CODE:实现略
}
上面的定义说明了类型参数T必须实现IComaprable接口,否则将无法通过编译,从而保证了方法体可以正确地运行。除了可以约束类型参数T实现某个接口以外,还可以约束T是一个结构、T是一个类、T拥有构造函数、T继承自某个基类等。
以下是我在项目中的部分应用:
1.在ASP.NET MVC DEMO中使用强类型,把datatable转换成ILIST(MODEL)
代码
2.根据MODEL来生成sqlparameter
#region ModelConvertHelper
public class ModelConvertHelper<T> where T : new()
{
public static IList<T> ConvertToModel( DataTable dt)
{
// 定义集合
IList<T> ts = new List<T>();
// 获得此模型的类型
Type type = typeof(T);
string tempName = "";
foreach (DataRow dr in dt.Rows)
{
T t = new T();
// 获得此模型的公共属性
PropertyInfo[] propertys = t.GetType().GetProperties();
foreach (PropertyInfo pi in propertys)
{
tempName = pi.Name;
// 检查DataTable是否包含此列
if (dt.Columns.Contains(tempName))
{
// 判断此属性是否有Setter
if (!pi.CanWrite) continue;
object value = dr[tempName];
if (value != DBNull.Value)
pi.SetValue(t, value, null);
}
}
ts.Add(t);
}
return ts;
}
}
#endregion
代码
#region PrepareParameterHelper
public class ModelParameterHelper
{
public static SqlParameter[] PrepareParametersFromModel<T>(T t)
{
string tempName = "";
int i = 0;
//属性数组
PropertyInfo[] propertys = t.GetType().GetProperties();
SqlParameter[] sqlParas = new SqlParameter[propertys.Length];
foreach (PropertyInfo pi in propertys)
{
tempName = pi.Name;
sqlParas[i++] = new SqlParameter("@"+tempName,pi.GetValue(t,null));
}
return sqlParas;
}
public static SqlParameter[] PrerpareParameterFromModelAndParaStr<T>(string [] parastr,T t)
{
string tempName = "";
int i = 0;
//属性数组
PropertyInfo[] propertys = t.GetType().GetProperties();
SqlParameter[] sqlParas = new SqlParameter[parastr.Length];
foreach (PropertyInfo pi in propertys)
{
tempName = pi.Name;
foreach (string s in parastr)
{
if (s.ToLower() == tempName.ToLower())
{
sqlParas[i++] = new SqlParameter("@" + tempName, pi.GetValue(t, null));
break;
}
}
}
return sqlParas;
}
}
#endregion.