c#利用反射+特性实现简单的实体映射数据库操作类(表与类的映射)
开始之前首先需要了解 特性Attribute; 说穿了特性也就是一些声明信息;我们在运行的时候可以用反射获取这些声明;
所想我们试想下;我们新建一个类用来存放数据库表中的信息; 那我们是不是需要在该类中有专门存放该表字段信息的类的字段呢?(这里说的是存放表中的全部字段信息)
在想想下,描述一个数据库字段需要哪些信息; 二类中字段可以满足哪些信息吗! 所以我们需要对该字段进行描述 ,比如说字段名称呀,字段数据类型呀,字段数据类型长度呀,还有有是否为主键呀?
我也是初学者 我这里只是说最基础的
建立特性类;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace DataTransfer
{
[AttributeUsage(AttributeTargets.Property,AllowMultiple = false ,Inherited = false )]
public class FieldAttribute:Attribute
{
private string _Fields;
/// <summary>
/// 字段名称
/// </summary>
public string Fields
{
get { return _Fields; }
}
private DbType _Dbtype;
/// <summary>
/// 字段类型
/// </summary>
public DbType Dbtype
{
get { return _Dbtype; }
}
private int _ValueLength;
/// <summary>
/// 字段值长度
/// </summary>
public int ValueLength
{
get { return _ValueLength; }
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="fields"> 字段名 </param>
/// <param name="types"> 字段类型 </param>
/// <param name="i"> 字段值长度 </param>
public FieldAttribute( string fields,DbType types, int i)
{
_Fields = fields;
_Dbtype = types;
_ValueLength = i;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataTransfer
{
[AttributeUsage(AttributeTargets.Class,AllowMultiple = false ,Inherited = false )]
public class TableAttribute:Attribute
{
private string _TableName;
/// <summary>
/// 映射的表名
/// </summary>
public string TableName
{
get { return _TableName; }
}
/// <summary>
/// 定位函数映射表名;
/// </summary>
/// <param name="table"></param>
public TableAttribute( string table)
{
_TableName = table;
}
}
}
这里是建立的2个特性类; 建立与表映射的类TableAttribute 外加与字段映射的类 FieldAttribute;
建立联系的类
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace DataTransfer
{
[Table( " Consumers " )] // 这里[Table("Consumers")] 或者 [TableAttribute("Consumers")] 是一样的效果
public class UserInf
{
private string _UserID;
/// <summary>
/// 登陆ID
/// </summary>
[Field( " ConsumerID " ,DbType.String, 12 )]
public string U_UserID
{
get { return _UserID; }
set { _UserID = value; }
}
private string _Psw;
/// <summary>
/// 登陆密码
/// </summary>
[Field( " ConsumerPwd " ,DbType.String, 12 )]
public string U_Psw
{
get { return _Psw; }
set { _Psw = value; }
}
private string _UserName;
/// <summary>
/// 用户别称
/// </summary>
[Field( " ConsumerName " ,DbType.String, 50 )]
public string U_UserName
{
get { return _UserName; }
set { _UserName = value; }
}
private string _City;
/// <summary>
/// 所住城市
/// </summary>
[Field( " UserCity " ,DbType.String, 50 )]
public string U_City
{
get { return _City; }
set { _City = value; }
}
private int _Popedom;
/// <summary>
/// 权限
/// </summary>
[Field( " popedom " , DbType.Int32, 0 )]
public int U_Popedom
{
get { return _Popedom; }
set { _Popedom = value; }
}
private DateTime _AddDataTime;
/// <summary>
/// 注册时间
/// </summary>
[Field( " addDataTime " ,DbType.Date, 0 )]
public DateTime U_AddDataTime
{
get { return _AddDataTime; }
set { _AddDataTime = value; }
}
private int _Sex;
/// <summary>
/// 性别
/// </summary>
[Field( " Sex " ,DbType.Int32, 0 )]
public int U_Sex
{
get { return _Sex; }
set { _Sex = value; }
}
private int _BirthTime;
/// <summary>
/// 出身日期;
/// </summary>
[Field( " BirthTime " , DbType.String, 9 )]
public int U_BirthTime
{
get { return _BirthTime; }
set { _BirthTime = value; }
}
}
}
userss.U_UserID = " aw12311 " ;
userss.U_Psw = " 123 " ;
userss.U_UserName = " aw " ;
userss.U_City = " 武汉 " ;
userss.U_Popedom = 1 ;
userss.U_Sex = 1 ;
userss.U_BirthTime = 19900114 ;
userss.U_AddDataTime = DateTime.Now;
/// 这里先让你查看字段描述;
查看表的特性;
Type userAttu = userss.GetType();
TableAttribute tables = (TableAttribute)userAttu.GetCustomAttributes( false )[ 0 ]; // 这里我在TableAttribute个类中写的是不容许多个描述,所以只有一个实例;
Response.Write(tables.TableName);
// 查看类中字段的描述
PropertyInfo[] info = userAttu.GetProperties();
foreach (PropertyInfo prs in info)
{
Response.Write( " --------------------------------</br> " );
object [] attu = prs.GetCustomAttributes( false );
object obj = prs.GetGetMethod().Invoke(userss, null ); // 取出当前描述字段的值
Response.Write(prs.Name + " | " + obj + " </br> " ); // 这里显示类中字段的名称 与值
foreach (Attribute abute in attu )
{
if (abute is FieldAttribute)
{
FieldAttribute column = abute as FieldAttribute;
Response.Write(column.Fields + " </br> " );
Response.Write(column.Dbtype + " </br> " );
Response.Write(column.ValueLength + " </br> " );
}
}
}
接着在 c# 中 传递帮他了的类拼接处查询字符串;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
namespace DataTransfer
{
public class DateIsTableAttribute < T >
{
public string insertDate(T types)
{
string cmdtxt = " insert into " ;
string cmdparVar = null ;
Type userAttu = types.GetType();
TableAttribute tables = (TableAttribute )userAttu.GetCustomAttributes( false )[ 0 ];
cmdtxt += tables.TableName + " ( " ;
PropertyInfo[] info = userAttu.GetProperties();
foreach (PropertyInfo prs in info)
{
object [] attu = prs.GetCustomAttributes( false );
foreach (Attribute abute in attu)
{
if (abute is FieldAttribute)
{
FieldAttribute midle = abute as FieldAttribute;
cmdtxt += midle.Fields + " , " ;
object obj = prs.GetGetMethod().Invoke(types, null );
if (midle.Dbtype == DbType.Int32)
cmdparVar += obj + " , " ;
else
cmdparVar += " ' " + obj + " ', " ;
}
}
}
cmdparVar = cmdparVar.Substring( 0 , cmdparVar.Length - 1 );
cmdtxt = cmdtxt.Substring( 0 , cmdtxt.Length - 1 ) + " ) " ;
cmdtxt += " values( " + cmdparVar + " ) " ;
return cmdtxt;
}
}
}
然后再aspx 中的页面调用该方法
DateIsTableAttribute<UserInf> t = new DateIsTableAttribute<UserInf>();
///此处的userss 是上面实例化并赋值的userss;
Response.Write(" </br>" + t.insertDate(userss));
//这样你就会看到拼接完成的 插入字符串;
这只是思路 当我们字段插入字符串后那对数据库的插入我们就应该是小意思了吧! 同理我们可以做出响应的修改删除;
当我们需要插入并一张表的时候,或者修改等 , 那我们只需要新建一个加特征的与我们需要映射的表就好了其他都不需要改了;当我们吧那些插入 修改 删除 都包装在一起 , 那我们就可以实现自动化了 ,我们唯一需要做的就是怎样去建立类与数据库的映射就好了!;
另外一个通用的操作类:
/// 获取用户数据库分页数据
/// </summary>
/// <param name="TableName"></param>
/// <param name="PageSize"></param>
/// <param name="PageIndex"></param>
/// <param name="SqlWhere"></param>
/// <returns></returns>
public DataSet GetList( string TableName, int PageSize, int PageIndex, string SqlWhere)
{
try
{
Assembly a = ReflectionUtil.LoadAssembly(Globals.UserDATA_Assembly + " .BLL " ); // 创建一个程序集
Type t = ReflectionUtil.GetType(a, Globals.UserDATA_Assembly + " .BLL. " + TableName + " BLL " );
object o = ReflectionUtil.CreateInstance(t, null );
Type[] types = new Type[ 3 ];
types[ 0 ] = Type.GetType( " System.Int32 " );
types[ 1 ] = Type.GetType( " System.Int32 " );
types[ 2 ] = Type.GetType( " System.String " );
MethodInfo mi = t.GetMethod( " GetList " , types);
Object[] obj = new Object[ 3 ];
obj[ 0 ] = PageSize;
obj[ 1 ] = PageIndex;
obj[ 2 ] = SqlWhere;
DataSet ds = (DataSet)mi.Invoke(o, obj);
return ds;
}
catch
{
return null ;
}
}
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;
namespace XINLG.Labs.Utils
{
/// <summary>
/// 反射操作类
/// </summary>
public class ReflectionUtil
{
#region 加载程序集
/// <summary>
/// 加载程序集
/// </summary>
/// <param name="assemblyName"> 程序集名称,不要加上程序集的后缀,如.dll </param>
public static Assembly LoadAssembly( string assemblyName)
{
try
{
return Assembly.Load(assemblyName);
}
catch ( Exception ex )
{
string errMsg = ex.Message;
return null ;
}
}
#endregion
#region 获取程序集中的类型
/// <summary>
/// 获取本地程序集中的类型
/// </summary>
/// <param name="typeName"> 类型名称,范例格式:"命名空间.类名",类型名称必须在本地程序集中 </param>
public static Type GetType( string typeName )
{
try
{
return Type.GetType( typeName );
}
catch ( Exception ex )
{
string errMsg = ex.Message;
return null ;
}
}
/// <summary>
/// 获取指定程序集中的类型
/// </summary>
/// <param name="assembly"> 指定的程序集 </param>
/// <param name="typeName"> 类型名称,范例格式:"命名空间.类名",类型名称必须在assembly程序集中 </param>
/// <returns></returns>
public static Type GetType( Assembly assembly , string typeName )
{
try
{
return assembly.GetType( typeName );
}
catch ( Exception ex )
{
string errMsg = ex.Message;
return null ;
}
}
#endregion
#region 动态创建对象实例
/// <summary>
/// 创建类型的实例
/// </summary>
/// <param name="type"> 类型 </param>
/// <param name="parameters"> 传递给构造函数的参数 </param>
public static object CreateInstance( Type type, params object [] parameters )
{
return Activator.CreateInstance( type, parameters );
}
/// <summary>
/// 创建类的实例
/// </summary>
/// <param name="className"> 类名,格式:"命名空间.类名" </param>
/// <param name="parameters"> 传递给构造函数的参数 </param>
public static object CreateInstance( string className, params object [] parameters )
{
try
{
// 获取类型
Type type = GetType( className );
// 类型为空则返回
if ( type == null )
{
return null ;
}
return CreateInstance( type, parameters );
}
catch ( Exception ex )
{
string errMsg = ex.Message;
return null ;
}
}
#endregion
#region 获取类的命名空间
/// <summary>
/// 获取类的命名空间
/// </summary>
/// <typeparam name="T"> 类名或接口名 </typeparam>
public static string GetNamespace < T > ()
{
return typeof ( T ).Namespace;
}
#endregion
#region 设置成员的值
#region 设置属性值
/// <summary>
/// 将值装载到目标对象的指定属性中
/// </summary>
/// <param name="target"> 要装载数据的目标对象 </param>
/// <param name="propertyName"> 目标对象的属性名 </param>
/// <param name="value"> 要装载的值 </param>
public static void SetPropertyValue( object target, string propertyName, object value )
{
PropertyInfo propertyInfo = target.GetType().GetProperty( propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy );
SetValue( target, propertyInfo, value );
}
#endregion
#region 设置成员的值
/// <summary>
/// 设置成员的值
/// </summary>
/// <param name="target"> 要装载数据的目标对象 </param>
/// <param name="memberInfo"> 目标对象的成员 </param>
/// <param name="value"> 要装载的值 </param>
private static void SetValue( object target, MemberInfo memberInfo, object value )
{
if ( value != null )
{
// 获取成员类型
Type pType;
if ( memberInfo.MemberType == MemberTypes.Property )
pType = ( (PropertyInfo)memberInfo ).PropertyType;
else
pType = ( (FieldInfo)memberInfo ).FieldType;
// 获取值的类型
Type vType = GetPropertyType( value.GetType() );
// 强制将值转换为属性类型
value = CoerceValue( pType, vType, value );
}
if ( memberInfo.MemberType == MemberTypes.Property )
( (PropertyInfo)memberInfo ).SetValue( target, value, null );
else
( (FieldInfo)memberInfo ).SetValue( target, value );
}
#endregion
#region 强制将值转换为指定类型
/// <summary>
/// 强制将值转换为指定类型
/// </summary>
/// <param name="propertyType"> 目标类型 </param>
/// <param name="valueType"> 值的类型 </param>
/// <param name="value"> 值 </param>
private static object CoerceValue( Type propertyType, Type valueType, object value )
{
// 如果值的类型与目标类型相同则直接返回,否则进行转换
if ( propertyType.Equals( valueType ) )
{
return value;
}
else
{
if ( propertyType.IsGenericType )
{
if ( propertyType.GetGenericTypeDefinition() == typeof ( Nullable <> ) )
{
if ( value == null )
return null ;
else if ( valueType.Equals( typeof ( string ) ) && ( string )value == string .Empty )
return null ;
}
propertyType = GetPropertyType( propertyType );
}
if ( propertyType.IsEnum && valueType.Equals( typeof ( string ) ) )
return Enum.Parse( propertyType, value.ToString() );
if ( propertyType.IsPrimitive && valueType.Equals( typeof ( string ) ) && string .IsNullOrEmpty( ( string )value ) )
value = 0 ;
try
{
return Convert.ChangeType( value, GetPropertyType( propertyType ) );
}
catch ( Exception ex )
{
TypeConverter cnv = TypeDescriptor.GetConverter( GetPropertyType( propertyType ) );
if ( cnv != null && cnv.CanConvertFrom( value.GetType() ) )
return cnv.ConvertFrom( value );
else
throw ex;
}
}
}
#endregion
#region 获取类型,如果类型为Nullable<>,则返回Nullable<>的基础类型
/// <summary>
/// 获取类型,如果类型为Nullable(of T),则返回Nullable(of T)的基础类型
/// </summary>
/// <param name="propertyType"> 需要转换的类型 </param>
private static Type GetPropertyType( Type propertyType )
{
Type type = propertyType;
if ( type.IsGenericType && ( type.GetGenericTypeDefinition() == typeof ( Nullable <> ) ) )
return Nullable.GetUnderlyingType( type );
return type;
}
#endregion
#endregion
}
}