反射学习系列2-特性(Attribute) – 你听海是不是在笑 – 博客园 -Mikel

反射学习系列2-特性(Attribute) – 你听海是不是在笑 – 博客园

2019年1月14日 分类: C#

来源: 反射学习系列2-特性(Attribute) – 你听海是不是在笑 – 博客园

反射学习系列目录

反射学习系列1-反射入门

反射学习系列2-特性(Attribute)

反射学习系列3-反射实例应用

作者

 

 

先看一个简单的例子
[Table(Name=”dbo.[User]”)]
public partial class User
{
C#编译器发现这个属性有一个特性Table时,首先会把字符串Attribute添加到这个名称的后面,形成一个组合名称TableAttribute,然后在其搜索路径的所有命名空间中搜索有相同类名的类。但要注意,如果该特性名结尾是Attribute,编译器就不会把该字符串加到组合名称中。所有的特性都是从System.Attribute类型上面派生的。
接着我们来看一下Table特性的定制格式
[AttributeUsageAttribute(AttributeTargets.Class, Inherited=true,AllowMultiple=false)]
public class TalbeAttribute:Attribute
{


在定义类型时使用System.AttributeUsage特性来表明这个自定义特性的使用范围,这里使用了Class样式,表示TableAttribute特性只能用在其它的Class类型前面,若放置在Interface或Struct类型前面,或者放在对象成员的前面则会出现编译错误。这里还是用语句 AllowMultiple=false 语句来表明对于一个类型,该特性只能用一次,若一个Class类型前面出现多个TableAttribute,则会出现编译错误。若设置AllowMultiple=true,则该特性可以多次定义,也就是一个Class类型前面可以出现多个相同类型的特性。不过这里我们假设一个对象只能映射到一个数据表上,没有多重映射,因此就指明对同一个类型该特性不能多次使用。Inherited参数设定为true,就表示应用到类或接口上的特性也可以自动应用到所派生的类或接口上。
我们再看一下定制TalbeAttribute特性的完整例子:

 

复制代码

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class TableAttribute : Attribute
{
//保存表名的字段
private string _tableName;

public TableAttribute()
{
}

public TableAttribute(string tableName)
{
this._tableName = tableName;
}

/// <summary>
/// 映射的表名(表的全名:模式名.表名)
/// </summary>
public string TableName
{
set
{
this._tableName = value;
}
get
{
return this._tableName;
}
}
}

复制代码

 

 特性也是一个Class类型,可以有多个构造函数,就像C#的new语句一样,我们向类型附加特性时可以使用不同的初始化参数来指明使用特性的那个构造函数。我们附加特性时还可以使用“属性名=属性值”的方法来直接指明特性的属性值。该特性中定义了一个TableName属性,该属性就是被修饰的对象所映射的数据库表的名称。

下面我们举一个使用特性来进行O/RMapping的例子,也就是将对象转化成SQL语句

用户类:

[Table(“User”)]
public class User
{
[Colum(“userID”, DbType = DbType.Int32)]
public int UserID { get; set; }
[Colum(“UserName”, DbType = DbType.String)]
public string UserName { get; set; }
}

 

表特性

 

表特性

 

列特性:

 


[AttributeUsageAttribute(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class ColumAttribute : Attribute
{
private string _columName;

private DbType _dbType ;

public ColumAttribute()
{
}

public ColumAttribute(string columName)
: this()
{
this._columName = columName;
}

public ColumAttribute(string columName, DbType dbType)
: this(columName)
{
this._dbType = dbType;
}

//列名
public virtual string ColumName
{
set
{
this._columName = value;
}
get
{
return this._columName;
}
}

//描述一些特殊的数据库类型
public DbType DbType
{
get { return _dbType; }
set { _dbType = value; }
}

}

 

 


public class ORMHelp
{
public void Insert(object table)
{
Type type = table.GetType();
//定义一个字典来存放表中字段和值的对应序列
Dictionary<string, string> columValue = new Dictionary<string, string>();
StringBuilder SQLStr=new StringBuilder();
SqlStr.Append(“insert into “);
//得到表名子
TableAttribute temp = (TalbeAttribute)type.GetCustomAttributes(typeof(TalbeAttribute), false).First();
SqlStr.Append(temp.TableName);
SqlStr.Append(“(“);
PropertyInfo[] Propertys=type.GetProperties();
foreach (var item in Propertys)
{
object[] attributes = item.GetCustomAttributes(false);
foreach (var item1 in attributes)
{
//获得相应属性的值
string value= table.GetType().InvokeMember(item.Name, System.Reflection.BindingFlags.GetProperty, null, table, null).ToString();
ColumAttribute colum = item1 as ColumAttribute;
if (colum != null)
{
columValue.Add(colum.ColumName,value);
}
}
}
//拼插入操作字符串
foreach (var item in columValue)
{
SqlStr.Append(item.Key);
SqlStr.Append(“,”);

}
SqlStr.Remove(SqlStr.Length-1, 1);
SqlStr.Append(“) values(‘”);
foreach (var item in columValue)
{
SqlStr.Append(item.Value);
SqlStr.Append(“‘,'”);

}
SqlStr.Remove(SqlStr.Length – 2, 2);
SqlStr.Append(“)”);
Console.WriteLine(SqlStr.ToString());

}
}

SqlStr中的内容为insert into User(userID,UserName) values(‘1′,’lfm’)

前端使用代码:

 


static void Main(string[] args)
{
ORMHelp o = new ORMHelp();
User u = new User() { UserID=1,UserName=”lfm”};
o.Insert(u);
}

作者

源码下载


标签:
本文的评论功能被关闭了.
备案信息冀ICP 0007948