案例1:比如说有时候我们需要将一些实体转换成另一个实体,并且相互之间没有什么继承关系,不能直接转换。
基础类:
namespace MapperDemo { /// <summary> /// 数据库实体类Student /// </summary> public class Student { public long QQ { get; set; } public int Age { get; set; } public int Id { get; set; } public string Name { get; set; } } /// <summary> /// 业务实体类StudentDto 用来绑定UI界面的数据模型。 /// /// </summary> public class StudentDto { public long QQ { get; set; } public int Age { get; set; } public int Id { get; set; } public string Name { get; set; } } }
方法1:可以使用反射来解决,但是需要注意的是这样的话其实也是比较耗性能的。
class Program { static void Main(string[] args) { Student student = new Student() { Id = 1, Age = 23, Name = "张三", QQ = 123123123, }; { //利用反射实现 StudentDto dto = Trans<Student, StudentDto>(student); } Console.WriteLine("Hello World!"); } /// <summary> /// 为了代码通用,使用泛型+反射 /// 反射是比较耗性能的 /// </summary> /// <typeparam name="TIn">传入类型</typeparam> /// <typeparam name="TOut">传出类型</typeparam> /// <param name="tIn"></param> /// <returns></returns> private static TOut Trans<TIn, TOut>(TIn tIn) { Type typeOut = typeof(TOut); Type typeIn = typeof(TIn); //获取类型的实例对象 TOut tOut = (TOut)Activator.CreateInstance(typeOut); //获取返回数据模型的所有属性信息 要给返回模型赋值,所以要遍历返回模型 foreach (var prop in typeOut.GetProperties()) { //获取此属性在传入模型中的信息 PropertyInfo property = typeIn.GetProperty(prop.Name); if (property == null) { continue; } prop.SetValue(tOut, property.GetValue(tIn)); } //给字段赋值 foreach (var field in typeOut.GetFields()) { //获取此属性在传入模型中的信息 FieldInfo fieldIn = typeIn.GetField(field.Name); if (fieldIn == null) { continue; } field.SetValue(tOut, fieldIn.GetValue(tIn)); } return tOut; } }
方法2:用表达式目录树Expression:它是一个数据结构,可以动态拼装,然后Compile()方法可以得到一个委托的实例。
方法3:使用特性来实现:
案例2: 比如说我们在提交数据的时候可能要对字段做是否为空验证,字段长度验证等,不使用特性的话我们就要对字段挨个进行判断,但是使用特性可以让我们避免这个操作:
这是模型类:
/// <summary> /// Company:数据表的真实名称 /// </summary> [TableMappingAttribute("Company")] public class CompanyModel { [LengthAttribute(3, 50)] public string CreateTime { get; set; } /// <summary> /// 在数据库表真实的字段是Name,和这里的不一样 /// </summary> [ColumnMappingAttribute("Name")] [LengthAttribute(3, 10)] public string NickName { get; set; } [RequiredAttribute] public Nullable<int> CreatorId { get; set; } public Nullable<int> LastModifierId { get; set; } public DateTime? LastModifyTime { get; set; } }
自定义的特性类:
namespace MyAttribute { /// <summary> /// 必填的自定义特性 /// 注意:加上 [AttributeUsage(AttributeTargets.Property)],用来限制只能用在属性上 /// </summary> [AttributeUsage(AttributeTargets.Property)] public class RequiredAttribute : AbstractAttribute { /// <summary> /// 重写继承方法 /// </summary> /// <param name="value"></param> /// <returns></returns> public override bool ValidateAll(object value) { if (value == null || string.IsNullOrWhiteSpace(value.ToString())) { return false; } return true; } } /// <summary> /// 校验长度 /// </summary> [AttributeUsage(AttributeTargets.Property)] public class LengthAttribute : AbstractAttribute { private int _Min = 0; private int _Max = 0; /// <summary> /// 长度范围赋值 /// </summary> /// <param name="min">允许最小长度值</param> /// <param name="max">允许最大长度值</param> public LengthAttribute(int min, int max) { this._Min = min; this._Max = max; } public int Min() { return this._Min; } public int Max() { return this._Max; } /// <summary> /// 重写继承方法 /// </summary> /// <param name="value"></param> /// <returns></returns> public override bool ValidateAll(object value) { if (value == null || value.ToString().Length < this._Min || value.ToString().Length > this._Max) { return false; } return true; } } /// <summary> /// 存在抽象方法就一定要是抽象类 /// /// </summary> [AttributeUsage(AttributeTargets.Property)] public abstract class AbstractAttribute : Attribute { public abstract bool ValidateAll(object value); } }
自定义的特性扩展方法,
namespace MyAttribute { /// <summary> /// 自定义的特性扩展方法类 /// </summary> public static class AttributeExtend { /// <summary> /// 通用的数据规则校验--通过泛型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static bool Validate<T>(this T t) { Type type = t.GetType(); foreach (var item in type.GetProperties()) { if (item.IsDefined(typeof(AbstractAttribute), true)) { object value = item.GetValue(t); foreach (AbstractAttribute attibute in item.GetCustomAttributes(typeof(AbstractAttribute), true)) { if (!attibute.ValidateAll(value)) { return false; } } } else { continue; } } return true; } } }
调用:
class Program { static void Main(string[] args) { SqlHelper sqlHelper = new SqlHelper(); CompanyModel company = sqlHelper.Query<CompanyModel>(1); company.CreatorId = null; if (!company.Validate()) { Console.WriteLine("校验失败"); } } }