特性是一种类,继承自Attribute,提供一些特殊的信息,本身并没有价值,只有在动态编程利用反射的时候才会体现出强大。

1.1 特性的简单使用

这里自定义了TestInfoAttribute特性,修饰了Student类,能够通过student实例通过反射获取到原数据。在编译过程中会有.custom的自定义实例产生,那一串01 00 06…就是“Albert”。不破坏封装,AOP面向切面编程。
image.png
image.png

  1. namespace AttributeExample {
  2. class Program {
  3. static void Main(string[] args) {
  4. Student student = new Student() { Age = 24, ID = 1 };
  5. Type type = student.GetType();
  6. if (type.IsDefined(typeof(TestInfoAttribute), true)) {
  7. TestInfoAttribute testInfoAttribute =(TestInfoAttribute) type.GetCustomAttribute(typeof(TestInfoAttribute));
  8. testInfoAttribute.PrintTestInfo();
  9. }
  10. }
  11. }
  12. [TestInfo("Albert")]
  13. public class Student {
  14. public int ID { get; set; }
  15. public int Age { get; set; }
  16. }
  17. [AttributeUsage(AttributeTargets.Class)]
  18. public class TestInfoAttribute : Attribute {
  19. private string _testInfo;
  20. public TestInfoAttribute(string testInfo) {
  21. _testInfo = testInfo;
  22. }
  23. public void PrintTestInfo() {
  24. Console.WriteLine(_testInfo);
  25. }
  26. }
  27. }

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 _Dictionary = new Dictionary();

  1. static void Main(string[] args) {
  2. Student student = new Student() { Age = 24, ID = 1, Name = "Albert" };
  3. //FirstMethod 使用Newtonsoft.Json序列号反序列化 此种方法效率很低
  4. string sStudent = JsonConvert.SerializeObject(student); //先序列化为字符串
  5. StudentDTO studentDTO = JsonConvert.DeserializeObject<StudentDTO>(sStudent);//反序列化
  6. //SecondMethod 使用automapper映射 专属的类型映射工具,为ORM而生 效率高
  7. Mapper.Initialize(x => x.CreateMap<Student, StudentDTO>());
  8. StudentDTO studentDTO1 = Mapper.Map<Student, StudentDTO>(student);
  9. //不同名称的映射
  10. //Mapper.Initialize(config=> {
  11. // config.CreateMap<Student, StudentDTO>().
  12. // ForMember(dest => dest.DickName, options => options.MapFrom(sou => sou.Name));
  13. //});
  14. //StudentDTO studentDTO2 = Mapper.Map<Student, StudentDTO>(student);
  15. //ThirdMethod 表达式目录树+静态缓存字典
  16. //表达式目录树+静态字典
  17. StudentDTO studentDTO3 = Trans<Student, StudentDTO>(student);
  18. //效率较高,表达式目录树+泛型缓存
  19. StudentDTO studentDTO4 = ExpressionGenericMapper<Student, StudentDTO>.Trans(student);
  20. }
  21. //表达式+静态字典
  22. public static TOut Trans<TIn,TOut>(TIn tIn) {
  23. TOut tOut = Activator.CreateInstance<TOut>();
  24. string key = string.Format("funckey_{0}_{1}", tIn.GetType().Name, tOut.GetType().Name);
  25. if (!_Dictionary.ContainsKey(key)) {
  26. ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
  27. List<MemberBinding> memberBindingsList = new List<MemberBinding>();
  28. foreach (var item in typeof(TOut).GetProperties()) {
  29. MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
  30. MemberBinding memberBinding = Expression.Bind(item, property);
  31. memberBindingsList.Add(memberBinding);
  32. }
  33. foreach (var item in typeof(TOut).GetFields()) {
  34. MemberExpression filed = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
  35. MemberBinding memberBinding = Expression.Bind(item, filed);
  36. memberBindingsList.Add(memberBinding);
  37. }
  38. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
  39. Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
  40. {
  41. parameterExpression
  42. });
  43. Func<TIn, TOut> func = lambda.Compile();
  44. _Dictionary[key] = func;
  45. }
  46. return ((Func<TIn, TOut>)_Dictionary[key]).Invoke(tIn);
  47. }
  48. }
  49. class Student {
  50. public int ID { get; set; }
  51. public string Name { get; set; }
  52. public int Age { get; set; }
  53. public void PrintAge() {
  54. Console.WriteLine(Age);
  55. }
  56. }
  57. class StudentDTO {
  58. public int ID { get; set; }
  59. public string Name { get; set; }
  60. //public string DickName { get; set; }
  61. public int Age { get; set; }
  62. public void PrintAge() {
  63. Console.WriteLine(Age);
  64. }
  65. }
  66. //表达式目录树+泛型缓存
  67. public class ExpressionGenericMapper<TIn, TOut> {
  68. private static Func<TIn, TOut> _FUNC = null;
  69. static ExpressionGenericMapper() {
  70. ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
  71. List<MemberBinding> memberBindingsList = new List<MemberBinding>();
  72. foreach (var item in typeof(TOut).GetProperties()) {
  73. MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
  74. MemberBinding memberBinding = Expression.Bind(item, property);
  75. memberBindingsList.Add(memberBinding);
  76. }
  77. foreach (var item in typeof(TOut).GetFields()) {
  78. MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
  79. MemberBinding memberBinding = Expression.Bind(item, property);
  80. memberBindingsList.Add(memberBinding);
  81. }
  82. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingsList.ToArray());
  83. Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
  84. {
  85. parameterExpression
  86. });
  87. _FUNC = lambda.Compile();//拼装是一次性的
  88. }
  89. public static TOut Trans(TIn tIn) {
  90. return _FUNC(tIn);
  91. }
  92. }

}

  1. <a name="JreM5"></a>
  2. ## 1.3 BS/CS开发 信息校验特性应用
  3. BS-用户提交信息-页面JS检查-提交到后端-后端还得校验一下,前端不可信-入库<br />CS-用户提交信息-后端校验-入库
  4. ```csharp
  5. namespace ExtendMethod {
  6. class Program {
  7. static void Main(string[] args) {
  8. int a = 5;
  9. int result = a.CalcAdd(5, 5);
  10. UserModel userModel = new UserModel();
  11. userModel.Account = "dfa";
  12. bool valid1 = userModel.Validate<UserModel>(); //扩展方法
  13. bool valid2 = AttributeExtend.Validate<UserModel>(userModel);
  14. Console.WriteLine(result);
  15. Console.WriteLine(valid1);
  16. Console.WriteLine(valid2);
  17. }
  18. //public static string GetName<T>(this T t) where T : MemberInfo {
  19. // if (t.IsDefined(typeof(T), true)) {
  20. // }
  21. //}
  22. }
  23. public static class Calc {
  24. public static int CalcAdd(this int a, int b, int c) {
  25. return a + b + c;
  26. }
  27. }
  28. public static class AttributeExtend {
  29. //一个方法完成不同类型的数据校验--泛型方法
  30. //得想办法知道,要检查的实体有啥属性,属性有啥规则
  31. //可以检查全部属性、可以为多个类型服务
  32. public static bool Validate<T>(this T input) {
  33. Type type = typeof(T);
  34. foreach (var item in type.GetProperties()) {
  35. if (item.IsDefined(typeof(AttributeBase), true)) {
  36. object oValue = item.GetValue(input);
  37. object[] oAttributeArray = item.GetCustomAttributes(typeof(AttributeBase), true);
  38. foreach (AttributeBase attribute in oAttributeArray) {
  39. if (attribute.Validate(oValue)) {
  40. return false;
  41. }
  42. }
  43. }
  44. }
  45. //foreach (var item in type.GetProperties()) {
  46. // if (item.IsDefined(typeof(ElevenRequiredAttribute), true)) {
  47. // object oValue = item.GetValue(input);//从input实例中获取属性值
  48. // ElevenRequiredAttribute el = (ElevenRequiredAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);
  49. // if (el.Validate()) {
  50. // Console.WriteLine("不合法");
  51. // return false;
  52. // }
  53. // }
  54. // if (item.IsDefined(typeof(ElevenLengthAttribute), true)) {
  55. // object oValue = item.GetValue(input);//从input实例中获取属性值
  56. // //可以获取属性item上特性的实例
  57. // ElevenLengthAttribute el = (ElevenLengthAttribute)item.GetCustomAttribute(typeof(ElevenLengthAttribute), true);
  58. // if (el.Validate()) {
  59. // Console.WriteLine("长度不对");
  60. // return false;
  61. // }
  62. // }
  63. //}
  64. return true;
  65. }
  66. }
  67. public class UserModel {
  68. public string ShortName { get; set; }
  69. [ElevenRequired]
  70. [ElevenLength(10, 20)]
  71. public string Account { get; set; }
  72. public string Password { get; set; }
  73. public string Email { get; set; }
  74. }
  75. /// <summary>
  76. /// 校验属性的基类
  77. /// </summary>
  78. public abstract class AttributeBase : Attribute {
  79. public abstract bool Validate(object oValue);
  80. }
  81. /// <summary>
  82. /// 非空特性
  83. /// </summary>
  84. public class ElevenRequiredAttribute : AttributeBase {
  85. public override bool Validate(object oValue) {
  86. if (oValue == null || string.IsNullOrWhiteSpace(oValue.ToString())) {
  87. Console.WriteLine("为空");
  88. return false;
  89. }
  90. else
  91. return true;
  92. }
  93. }
  94. public class ElevenLengthAttribute : AttributeBase {
  95. private int _Min = 0;
  96. private int _Max = 0;
  97. public ElevenLengthAttribute(int min, int max) {
  98. _Min = min;
  99. _Max = max;
  100. }
  101. public override bool Validate(object oValue) {
  102. if (oValue.ToString().Length <= _Min && oValue.ToString().Length >= _Max) {
  103. Console.WriteLine("长度不对");
  104. return false;
  105. }
  106. else
  107. return true;
  108. }
  109. }
  110. }