自己写Facotry-解析.Net 的反射和attribute
很多人都知道工厂,知道反射,但是真正能用的好的并不多,我也是最近才真正明白了什么是反射,反射和.Net 里的一些其他特性是怎么应用的。在这里,分享一个自己写的小的数据库工厂的架构,和大家讨论。
目的的需求
:
在一个系统里,需要有一个统一的数据库类实现对SQL Server的增删改查
,要求有良好的扩展行和维护性。
在知道反射和属性之前的思路,是对每个实体类写相应的操作。但是现在,可以通过应用Attribute来进行自己定义
首先,要把数据库里的表和实体类对应.这样,我们简单的定义一个属性ClassesDefineSqlAttribute,用对应表和实体类。
[AttributeUsage(AttributeTargets.Class)]
class ClassesDefineSqlAttribute :Attribute
{
public String SqlTableName { get; set; }
public ClassesDefineSqlAttribute()
{
}
}
class ClassesDefineSqlAttribute :Attribute
{
public String SqlTableName { get; set; }
public ClassesDefineSqlAttribute()
{
}
}
第一步对应好了以后,下一步要将实体类的属性与数据库表中的列进行对应,为此,定义 ClassesDefineColumnAttribute 这里,只是简单的设置了列名,列的类型(数据,主键,改之前的主键),呵呵,一切从简,够用就好
public enum ColType
{
/// <summary>
/// 数据列
/// </summary>
Data,
/// <summary>
/// 主键列
/// </summary>
ClassCode,
/// <summary>
/// 级别列(在树型结构中用到)
/// </summary>
ClassLevel,
/// <summary>
/// 旧键(更新时使用)
/// </summary>
OldCode
}
[AttributeUsage(AttributeTargets.Property )]
public class ClassesDefineColumnAttribute:Attribute
{
//对应的数据库列名
public string SqlColName { get; set; }
/// <summary>
/// 列的类型
/// </summary>
public ColType ColType { get; set; }
/// <summary>
/// 复杂类型的属性值
/// </summary>
public string TargetProperty { get; set; }
}
}
{
/// <summary>
/// 数据列
/// </summary>
Data,
/// <summary>
/// 主键列
/// </summary>
ClassCode,
/// <summary>
/// 级别列(在树型结构中用到)
/// </summary>
ClassLevel,
/// <summary>
/// 旧键(更新时使用)
/// </summary>
OldCode
}
[AttributeUsage(AttributeTargets.Property )]
public class ClassesDefineColumnAttribute:Attribute
{
//对应的数据库列名
public string SqlColName { get; set; }
/// <summary>
/// 列的类型
/// </summary>
public ColType ColType { get; set; }
/// <summary>
/// 复杂类型的属性值
/// </summary>
public string TargetProperty { get; set; }
}
}
用了这些准备,就可以在数据工厂中完成增删改查了
为了通用,我们把增删改的参数都设置成object ,这样,在操作时,先将object 的最终类别取到,然后得到上面的几个属性,动态的生成SQL语句
先看增操作
public void Create(object T)
{
var info = T.GetType();//得到要新建的类型
ClassesDefineSqlAttribute attribute =
(ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info,
typeof(ClassesDefineSqlAttribute));///得到表名
if (attribute != null)
{
var Properties = info.GetProperties();///得到属性
System.Reflection.PropertyInfo KeyProperty = null;
String insert = "INSERT " + attribute.SqlTableName + "(";
String values = ") Values(";
String checksql = "";
String GetKeySql = "WHERE 1=1";
foreach (var infoattr in Properties)
{
var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var a = attr as ClassesDefineColumnAttribute;
if (a.ColType != ColType.OldCode)
{
if (a.ColType != ColType.ClassCode
||
infoattr.PropertyType == typeof(String))
{
string valuestr = (infoattr.GetValue(T, null) ?? "").ToString();
insert += a.SqlColName + ",";
values += "'" + valuestr + "',";
GetKeySql = GetKeySql + " And " + a.SqlColName + "='" + valuestr + "'";
}
if (a.ColType == ColType.ClassCode)
{
KeyProperty = infoattr;
if (KeyProperty.PropertyType == typeof(String))
{
checksql = "Select Count(*) FROM " + attribute.SqlTableName + " Where " + a.SqlColName + "='" + (infoattr.GetValue(T, null) ?? "").ToString() + "'";
if (System.Convert.ToInt32(
new DataConnectionFactory().GetDataTable(checksql).Rows[0][0]) > 0)
throw new Exception("无法生成新数据,与现有数据编码相同!");
}
else
{
GetKeySql = "Select " + a.SqlColName + " FROM " + attribute.SqlTableName + " " + GetKeySql;
}
}
}
}
}
}
String sql = insert.Substring(0, insert.Length - 1) + values.Substring(0, values.Length - 1) + ")";
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
//设置 自增长主键的返回直
if (KeyProperty.PropertyType != typeof(string))
{
KeyProperty.SetValue(T,
new DataConnectionFactory().GetDataTable(GetKeySql).Rows[0][0], null);
}
}
}
else
{
throw new Exception("类型不符合要求");
}
}
{
var info = T.GetType();//得到要新建的类型
ClassesDefineSqlAttribute attribute =
(ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info,
typeof(ClassesDefineSqlAttribute));///得到表名
if (attribute != null)
{
var Properties = info.GetProperties();///得到属性
System.Reflection.PropertyInfo KeyProperty = null;
String insert = "INSERT " + attribute.SqlTableName + "(";
String values = ") Values(";
String checksql = "";
String GetKeySql = "WHERE 1=1";
foreach (var infoattr in Properties)
{
var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var a = attr as ClassesDefineColumnAttribute;
if (a.ColType != ColType.OldCode)
{
if (a.ColType != ColType.ClassCode
||
infoattr.PropertyType == typeof(String))
{
string valuestr = (infoattr.GetValue(T, null) ?? "").ToString();
insert += a.SqlColName + ",";
values += "'" + valuestr + "',";
GetKeySql = GetKeySql + " And " + a.SqlColName + "='" + valuestr + "'";
}
if (a.ColType == ColType.ClassCode)
{
KeyProperty = infoattr;
if (KeyProperty.PropertyType == typeof(String))
{
checksql = "Select Count(*) FROM " + attribute.SqlTableName + " Where " + a.SqlColName + "='" + (infoattr.GetValue(T, null) ?? "").ToString() + "'";
if (System.Convert.ToInt32(
new DataConnectionFactory().GetDataTable(checksql).Rows[0][0]) > 0)
throw new Exception("无法生成新数据,与现有数据编码相同!");
}
else
{
GetKeySql = "Select " + a.SqlColName + " FROM " + attribute.SqlTableName + " " + GetKeySql;
}
}
}
}
}
}
String sql = insert.Substring(0, insert.Length - 1) + values.Substring(0, values.Length - 1) + ")";
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
//设置 自增长主键的返回直
if (KeyProperty.PropertyType != typeof(string))
{
KeyProperty.SetValue(T,
new DataConnectionFactory().GetDataTable(GetKeySql).Rows[0][0], null);
}
}
}
else
{
throw new Exception("类型不符合要求");
}
}
增操作完成,改的操作也很类似
public void Save(object T)
{
var info = T.GetType();
ClassesDefineSqlAttribute attribute = (ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info, typeof(ClassesDefineSqlAttribute));
String oldCode = "";
String newCode = "";
bool HaveOldCode = false;
System.Reflection.PropertyInfo KeyProperty = null;
if (attribute != null)
{
var Properties = info.GetProperties();
String insert = "UPDATE " + attribute.SqlTableName + " SET ";
String wheresql = "";
String checksql = "";
foreach (var infoattr in Properties)
{
var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var valueStr = infoattr.GetValue(T, null).ToString();
var a = attr as ClassesDefineColumnAttribute;
if (attr.ColType == ColType.Data
|| (attr.ColType == ColType.ClassCode && infoattr.PropertyType == typeof(String)))
insert += a.SqlColName + "='" + valueStr + "',";
if (a.ColType == ColType.ClassCode)
{
checksql = a.SqlColName + "='" + valueStr + "'";
KeyProperty = infoattr;
newCode = valueStr;
}
if (a.ColType == ColType.OldCode)
{
HaveOldCode = true;
wheresql = " Where " + a.SqlColName + "='" + valueStr + "'";
oldCode = valueStr;
}
}
}
}
if (HaveOldCode)
{
if (newCode != oldCode)
{
checksql = "Select count(*) FROM " + attribute.SqlTableName + wheresql + " OR " + checksql;
if (System.Convert.ToInt32(
new DataConnectionFactory().GetDataTable(checksql).Rows[0][0]) >= 2)
throw new Exception("无法生成新数据,与现有数据编码相同!");
}
}
else
wheresql = "Where " + checksql;
String sql = insert.Substring(0, insert.Length - 1) + wheresql;
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
}
}
else
{
throw new Exception("类型不符合要求");
}
}
{
var info = T.GetType();
ClassesDefineSqlAttribute attribute = (ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info, typeof(ClassesDefineSqlAttribute));
String oldCode = "";
String newCode = "";
bool HaveOldCode = false;
System.Reflection.PropertyInfo KeyProperty = null;
if (attribute != null)
{
var Properties = info.GetProperties();
String insert = "UPDATE " + attribute.SqlTableName + " SET ";
String wheresql = "";
String checksql = "";
foreach (var infoattr in Properties)
{
var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var valueStr = infoattr.GetValue(T, null).ToString();
var a = attr as ClassesDefineColumnAttribute;
if (attr.ColType == ColType.Data
|| (attr.ColType == ColType.ClassCode && infoattr.PropertyType == typeof(String)))
insert += a.SqlColName + "='" + valueStr + "',";
if (a.ColType == ColType.ClassCode)
{
checksql = a.SqlColName + "='" + valueStr + "'";
KeyProperty = infoattr;
newCode = valueStr;
}
if (a.ColType == ColType.OldCode)
{
HaveOldCode = true;
wheresql = " Where " + a.SqlColName + "='" + valueStr + "'";
oldCode = valueStr;
}
}
}
}
if (HaveOldCode)
{
if (newCode != oldCode)
{
checksql = "Select count(*) FROM " + attribute.SqlTableName + wheresql + " OR " + checksql;
if (System.Convert.ToInt32(
new DataConnectionFactory().GetDataTable(checksql).Rows[0][0]) >= 2)
throw new Exception("无法生成新数据,与现有数据编码相同!");
}
}
else
wheresql = "Where " + checksql;
String sql = insert.Substring(0, insert.Length - 1) + wheresql;
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
}
}
else
{
throw new Exception("类型不符合要求");
}
}
最后是删除的操作
public void Delete(object T)
{
var info = T.GetType();
ClassesDefineSqlAttribute attribute = (ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info, typeof(ClassesDefineSqlAttribute));
TreeNodeAttribute treedef = (TreeNodeAttribute)Attribute.GetCustomAttribute(info, typeof(TreeNodeAttribute));
if (attribute != null)
{
var Properties = info.GetProperties();
String insert = "Delete " + attribute.SqlTableName + " ";
foreach (var infoattr in Properties)
{ var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var valueStr = infoattr.GetValue(T, null).ToString();
var a = attr as ClassesDefineColumnAttribute;
if (a.ColType == ColType.OldCode)
{
insert += " Where " + a.SqlColName + "='" + valueStr + "'";
break;
}
else if (a.ColType == ColType.ClassCode)
{
insert += " Where " + a.SqlColName + "='" + valueStr + "'";
break;
}
}
}
}
String sql = insert;
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
}
}
else
{
throw new Exception("类型不符合要求");
}
}
{
var info = T.GetType();
ClassesDefineSqlAttribute attribute = (ClassesDefineSqlAttribute)Attribute.GetCustomAttribute(info, typeof(ClassesDefineSqlAttribute));
TreeNodeAttribute treedef = (TreeNodeAttribute)Attribute.GetCustomAttribute(info, typeof(TreeNodeAttribute));
if (attribute != null)
{
var Properties = info.GetProperties();
String insert = "Delete " + attribute.SqlTableName + " ";
foreach (var infoattr in Properties)
{ var ob = Attribute.GetCustomAttribute(infoattr, typeof(ClassesDefineColumnAttribute));
if (ob != null)
{
var attr = ob as ClassesDefineColumnAttribute;
if (attr is ClassesDefineColumnAttribute)
{
var valueStr = infoattr.GetValue(T, null).ToString();
var a = attr as ClassesDefineColumnAttribute;
if (a.ColType == ColType.OldCode)
{
insert += " Where " + a.SqlColName + "='" + valueStr + "'";
break;
}
else if (a.ColType == ColType.ClassCode)
{
insert += " Where " + a.SqlColName + "='" + valueStr + "'";
break;
}
}
}
}
String sql = insert;
using (var db = new DataConnectionFactory().GetConnection())
{
db.ExecuteCommand(sql);
}
}
else
{
throw new Exception("类型不符合要求");
}
}
这样,再有类型 ,只要做好相应的标记,便 可直接应用这个类了
如我的表示档案盒的类型FileBox
[ClassesDefineSql(SqlTableName = "DA_FileBox")]
public class FileBox
{
/// <summary>
/// 档案盒
/// </summary>
[ClassesDefineColumn(ColType = ColType.ClassCode, SqlColName = "BoxNo")]
public String BoxNo
{
get;
set;
}
/// <summary>
/// 标签ID
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "TagNo")]
public string TagID
{
get;
set;
}
/// <summary>
/// 类别信息
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "ClassNo")]
public string ClassNo
{
get;
set;
}
/// <summary>
/// 类别名称
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "ClassName")]
public string ClassName
{
get;
set;
}
/// <summary>
/// 位置编号
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "LocationNo")]
public string LocationNo
{
get;
set;
}
/// <summary>
/// 位置说明
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "LocationName")]
public string LocationName
{
get;
set;
}
/// <summary>
/// 备用一
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "Note1")]
public string Note1
{
get;
set;
}
/// <summary>
/// 备用二
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "Note2")]
public string Note2
{
get;
set;
}
}
public class FileBox
{
/// <summary>
/// 档案盒
/// </summary>
[ClassesDefineColumn(ColType = ColType.ClassCode, SqlColName = "BoxNo")]
public String BoxNo
{
get;
set;
}
/// <summary>
/// 标签ID
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "TagNo")]
public string TagID
{
get;
set;
}
/// <summary>
/// 类别信息
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "ClassNo")]
public string ClassNo
{
get;
set;
}
/// <summary>
/// 类别名称
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "ClassName")]
public string ClassName
{
get;
set;
}
/// <summary>
/// 位置编号
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "LocationNo")]
public string LocationNo
{
get;
set;
}
/// <summary>
/// 位置说明
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "LocationName")]
public string LocationName
{
get;
set;
}
/// <summary>
/// 备用一
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "Note1")]
public string Note1
{
get;
set;
}
/// <summary>
/// 备用二
/// </summary>
[ClassesDefineColumn(ColType = ColType.Data, SqlColName = "Note2")]
public string Note2
{
get;
set;
}
}