特性是一种类,继承自Attribute,提供一些特殊的信息,本身并没有价值,只有在动态编程利用反射的时候才会体现出强大。
1.1 特性的简单使用
这里自定义了TestInfoAttribute特性,修饰了Student类,能够通过student实例通过反射获取到原数据。在编译过程中会有.custom的自定义实例产生,那一串01 00 06…就是“Albert”。不破坏封装,AOP面向切面编程。

namespace AttributeExample {class Program {static void Main(string[] args) {Student student = new Student() { Age = 24, ID = 1 };Type type = student.GetType();if (type.IsDefined(typeof(TestInfoAttribute), true)) {TestInfoAttribute testInfoAttribute =(TestInfoAttribute) type.GetCustomAttribute(typeof(TestInfoAttribute));testInfoAttribute.PrintTestInfo();}}}[TestInfo("Albert")]public class Student {public int ID { get; set; }public int Age { get; set; }}[AttributeUsage(AttributeTargets.Class)]public class TestInfoAttribute : Attribute {private string _testInfo;public TestInfoAttribute(string testInfo) {_testInfo = testInfo;}public void PrintTestInfo() {Console.WriteLine(_testInfo);}}}
1.2 Student转换为StudentDTO几种方式
首先是硬编码的方式效率是最高的,但是没办法做成通用的方法,代码后期可维护性和扩展性变低。选择低一点的版本使用,不然可能找不到一些常用的方法。
- Json序列化、反序列化
- AutoMapper 类映射
- 静态字典缓存+表达式目录树
- 泛型缓存+表达式目录树 ```csharp using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AutoMapper; using System.Linq.Expressions; using DynamicExpresso; using Gremlin.Net.Process.Traversal;
namespace DTOExample {
class Program {
public static Dictionary
static void Main(string[] args) {Student student = new Student() { Age = 24, ID = 1, Name = "Albert" };//FirstMethod 使用Newtonsoft.Json序列号反序列化 此种方法效率很低string sStudent = JsonConvert.SerializeObject(student); //先序列化为字符串StudentDTO studentDTO = JsonConvert.DeserializeObject<StudentDTO>(sStudent);//反序列化//SecondMethod 使用automapper映射 专属的类型映射工具,为ORM而生 效率高Mapper.Initialize(x => x.CreateMap<Student, StudentDTO>());StudentDTO studentDTO1 = Mapper.Map<Student, StudentDTO>(student);//不同名称的映射//Mapper.Initialize(config=> {// config.CreateMap<Student, StudentDTO>().// ForMember(dest => dest.DickName, options => options.MapFrom(sou => sou.Name));//});//StudentDTO studentDTO2 = Mapper.Map<Student, StudentDTO>(student);//ThirdMethod 表达式目录树+静态缓存字典//表达式目录树+静态字典StudentDTO studentDTO3 = Trans<Student, StudentDTO>(student);//效率较高,表达式目录树+泛型缓存StudentDTO studentDTO4 = ExpressionGenericMapper<Student, StudentDTO>.Trans(student);}//表达式+静态字典public static TOut Trans<TIn,TOut>(TIn tIn) {TOut tOut = Activator.CreateInstance<TOut>();string key = string.Format("funckey_{0}_{1}", tIn.GetType().Name, tOut.GetType().Name);if (!_Dictionary.ContainsKey(key)) {ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");List<MemberBinding> memberBindingsList = new List<MemberBinding>();foreach (var item in typeof(TOut).GetProperties()) {MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingsList.Add(memberBinding);}foreach (var item in typeof(TOut).GetFields()) {MemberExpression filed = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));MemberBinding memberBinding = Expression.Bind(item, filed);memberBindingsList.Add(memberBinding);}MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]{parameterExpression});Func<TIn, TOut> func = lambda.Compile();_Dictionary[key] = func;}return ((Func<TIn, TOut>)_Dictionary[key]).Invoke(tIn);}}class Student {public int ID { get; set; }public string Name { get; set; }public int Age { get; set; }public void PrintAge() {Console.WriteLine(Age);}}class StudentDTO {public int ID { get; set; }public string Name { get; set; }//public string DickName { get; set; }public int Age { get; set; }public void PrintAge() {Console.WriteLine(Age);}}//表达式目录树+泛型缓存public class ExpressionGenericMapper<TIn, TOut> {private static Func<TIn, TOut> _FUNC = null;static ExpressionGenericMapper() {ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");List<MemberBinding> memberBindingsList = new List<MemberBinding>();foreach (var item in typeof(TOut).GetProperties()) {MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingsList.Add(memberBinding);}foreach (var item in typeof(TOut).GetFields()) {MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));MemberBinding memberBinding = Expression.Bind(item, property);memberBindingsList.Add(memberBinding);}MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]{parameterExpression});_FUNC = lambda.Compile();//拼装是一次性的}public static TOut Trans(TIn tIn) {return _FUNC(tIn);}}
}
<a name="JreM5"></a>## 1.3 BS/CS开发 信息校验特性应用BS-用户提交信息-页面JS检查-提交到后端-后端还得校验一下,前端不可信-入库<br />CS-用户提交信息-后端校验-入库```csharpnamespace ExtendMethod {class Program {static void Main(string[] args) {int a = 5;int result = a.CalcAdd(5, 5);UserModel userModel = new UserModel();userModel.Account = "dfa";bool valid1 = userModel.Validate<UserModel>(); //扩展方法bool valid2 = AttributeExtend.Validate<UserModel>(userModel);Console.WriteLine(result);Console.WriteLine(valid1);Console.WriteLine(valid2);}//public static string GetName<T>(this T t) where T : MemberInfo {// if (t.IsDefined(typeof(T), true)) {// }//}}public static class Calc {public static int CalcAdd(this int a, int b, int c) {return a + b + c;}}public static class AttributeExtend {//一个方法完成不同类型的数据校验--泛型方法//得想办法知道,要检查的实体有啥属性,属性有啥规则//可以检查全部属性、可以为多个类型服务public static bool Validate<T>(this T input) {Type type = typeof(T);foreach (var item in type.GetProperties()) {if (item.IsDefined(typeof(AttributeBase), true)) {object oValue = item.GetValue(input);object[] oAttributeArray = item.GetCustomAttributes(typeof(AttributeBase), true);foreach (AttributeBase attribute in oAttributeArray) {if (attribute.Validate(oValue)) {return false;}}}}//foreach (var item in type.GetProperties()) {// if (item.IsDefined(typeof(ElevenRequiredAttribute), true)) {// object oValue = item.GetValue(input);//从input实例中获取属性值// ElevenRequiredAttribute el = (ElevenRequiredAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);// if (el.Validate()) {// Console.WriteLine("不合法");// return false;// }// }// if (item.IsDefined(typeof(ElevenLengthAttribute), true)) {// object oValue = item.GetValue(input);//从input实例中获取属性值// //可以获取属性item上特性的实例// ElevenLengthAttribute el = (ElevenLengthAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);// if (el.Validate()) {// Console.WriteLine("长度不对");// return false;// }// }//}return true;}}public class UserModel {public string ShortName { get; set; }[ElevenRequired][ElevenLength(10, 20)]public string Account { get; set; }public string Password { get; set; }public string Email { get; set; }}/// <summary>/// 校验属性的基类/// </summary>public abstract class AttributeBase : Attribute {public abstract bool Validate(object oValue);}/// <summary>/// 非空特性/// </summary>public class ElevenRequiredAttribute : AttributeBase {public override bool Validate(object oValue) {if (oValue == null || string.IsNullOrWhiteSpace(oValue.ToString())) {Console.WriteLine("为空");return false;}elsereturn true;}}public class ElevenLengthAttribute : AttributeBase {private int _Min = 0;private int _Max = 0;public ElevenLengthAttribute(int min, int max) {_Min = min;_Max = max;}public override bool Validate(object oValue) {if (oValue.ToString().Length <= _Min && oValue.ToString().Length >= _Max) {Console.WriteLine("长度不对");return false;}elsereturn true;}}}
