SRP Single Responsibility Principle 单一职责原则(站在服务提供者的角度来看)
ISP Interface Segregation Principle 接口隔离原则(站在服务调用者的角度来看):把本质不同的接口隔离开,服务调用者不会多要。
胖接口ITank,违反了接口隔离原则

  1. using System;
  2. namespace ISP_InterfaceSegregationPrinciple_
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. var driver = new Driver(new Car());
  9. driver.Drive();
  10. }
  11. }
  12. class Driver
  13. {
  14. private IVehicle _vehicle;
  15. public Driver(IVehicle vehicle)
  16. {
  17. _vehicle = vehicle;
  18. }
  19. public void Drive()
  20. {
  21. _vehicle.Run();
  22. }
  23. }
  24. interface IVehicle
  25. {
  26. void Run();
  27. }
  28. class Car : IVehicle
  29. {
  30. public void Run()
  31. {
  32. Console.WriteLine("Car is runnning");
  33. }
  34. }
  35. class Truck : IVehicle
  36. {
  37. public void Run()
  38. {
  39. Console.WriteLine("Truck is runnning");
  40. }
  41. }
  42. interface ITank //胖接口
  43. {
  44. void Fire(); //隶属于武器
  45. void Run(); //隶属于机动车辆
  46. }
  47. class LightTank : ITank
  48. {
  49. public void Fire()
  50. {
  51. Console.WriteLine("Boom");
  52. }
  53. public void Run()
  54. {
  55. Console.WriteLine("Ka ka ka...");
  56. }
  57. }
  58. class MediumTank : ITank
  59. {
  60. public void Fire()
  61. {
  62. Console.WriteLine("Medium Boom");
  63. }
  64. public void Run()
  65. {
  66. Console.WriteLine("Ka!ka! ka!...");
  67. }
  68. }
  69. class HeavyTank : ITank
  70. {
  71. public void Fire()
  72. {
  73. Console.WriteLine("Heavy Boom");
  74. }
  75. public void Run()
  76. {
  77. Console.WriteLine("Ka!! ka!! ka!!...");
  78. }
  79. }
  80. }

重构:实现多个基接口

  1. using System;
  2. namespace ISP_InterfaceSegregationPrinciple_
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. var driver = new Driver(new HeavyTank());
  9. driver.Drive();
  10. }
  11. }
  12. class Driver
  13. {
  14. private IVehicle _vehicle;
  15. public Driver(IVehicle vehicle)
  16. {
  17. _vehicle = vehicle;
  18. }
  19. public void Drive()
  20. {
  21. _vehicle.Run();
  22. }
  23. }
  24. interface IVehicle
  25. {
  26. void Run();
  27. }
  28. class Car : IVehicle
  29. {
  30. public void Run()
  31. {
  32. Console.WriteLine("Car is runnning");
  33. }
  34. }
  35. class Truck : IVehicle
  36. {
  37. public void Run()
  38. {
  39. Console.WriteLine("Truck is runnning");
  40. }
  41. }
  42. interface IWeapon
  43. {
  44. void Fire();
  45. }
  46. interface ITank:IWeapon,IVehicle //胖接口
  47. {
  48. }
  49. class LightTank : ITank
  50. {
  51. public void Fire()
  52. {
  53. Console.WriteLine("Boom");
  54. }
  55. public void Run()
  56. {
  57. Console.WriteLine("Ka ka ka...");
  58. }
  59. }
  60. class MediumTank : ITank
  61. {
  62. public void Fire()
  63. {
  64. Console.WriteLine("Medium Boom");
  65. }
  66. public void Run()
  67. {
  68. Console.WriteLine("Ka!ka! ka!...");
  69. }
  70. }
  71. class HeavyTank : ITank
  72. {
  73. public void Fire()
  74. {
  75. Console.WriteLine("Heavy Boom");
  76. }
  77. public void Run()
  78. {
  79. Console.WriteLine("Ka!! ka!! ka!!...");
  80. }
  81. }
  82. }

1 显示接口实现

1.1 隐式实现

  1. using System;
  2. namespace IspExample
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. var Albert = new WarmKiller();
  9. Albert.Kill();
  10. Albert.Love();//两个方法都能被看见,不符合现实世界中的逻辑
  11. }
  12. }
  13. interface IGentleman
  14. {
  15. void Love();
  16. }
  17. interface IKiller
  18. {
  19. void Kill();
  20. }
  21. class WarmKiller : IGentleman,IKiller
  22. {
  23. public void Kill()
  24. {
  25. Console.WriteLine("Let me kill the enemy..");
  26. }
  27. public void Love()
  28. {
  29. Console.WriteLine("i will love you for ever..");
  30. }
  31. }
  32. }

1.2 显示实现

  1. using System;
  2. namespace IspExample
  3. {
  4. class Program
  5. {
  6. static void Main(string[] args)
  7. {
  8. var Albert = new WarmKiller();
  9. Albert.Love();//只能看见Love
  10. IKiller killer = Albert;
  11. killer.Kill();//只能看见Kill,两种方法:强制类型转换,as
  12. var wk = (IGentleman)killer;
  13. wk.Love();
  14. }
  15. }
  16. interface IGentleman
  17. {
  18. void Love();
  19. }
  20. interface IKiller
  21. {
  22. void Kill();
  23. }
  24. class WarmKiller : IGentleman,IKiller
  25. {
  26. public void Love()
  27. {
  28. Console.WriteLine("i will love you for ever..");
  29. }
  30. void IKiller.Kill() //显示实现其接口
  31. {
  32. Console.WriteLine("Let me kill the enemy..");
  33. }
  34. }
  35. }

2 反射(.Net框架特有的功能)Reflection与依赖注入

C#托管类型的语言

  • 反射:以不变应万变(更松的耦合)
  • 反射与接口的结合
  • 反射与特性的结合
  • 依赖注入:此DI非彼DI,但没有彼DI被没有此DI….

反射有什么用:程序的逻辑有时候不是我们写程序的时候能确定的,程序处于动态状态。以不变应万变的能力。

2.1 反射的原理以及与反射相关的重要技能依赖注入

.NETFramework和.NETCore 反射的API不同

反射的实现

  1. using System;
  2. using System.Reflection;
  3. namespace ISP_InterfaceSegregationPrinciple_
  4. {
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. ITank tank = new HeavyTank();
  10. // =========反射=========
  11. var t = tank.GetType(); //获得类型信息
  12. object o = Activator.CreateInstance(t);//激活创建一个实例,不通过new创建
  13. MethodInfo fileMi = t.GetMethod("Fire");
  14. MethodInfo runMi = t.GetMethod("Run"); //获得方法的信息
  15. fileMi.Invoke(o, null);
  16. runMi.Invoke(o, null);//方法必须依托一个实例,第二个值为函数的参数
  17. }
  18. }
  19. class Driver
  20. {
  21. private IVehicle _vehicle;
  22. public Driver(IVehicle vehicle)
  23. {
  24. _vehicle = vehicle;
  25. }
  26. public void Drive()
  27. {
  28. _vehicle.Run();
  29. }
  30. }
  31. interface IVehicle
  32. {
  33. void Run();
  34. }
  35. class Car : IVehicle
  36. {
  37. public void Run()
  38. {
  39. Console.WriteLine("Car is runnning");
  40. }
  41. }
  42. class Truck : IVehicle
  43. {
  44. public void Run()
  45. {
  46. Console.WriteLine("Truck is runnning");
  47. }
  48. }
  49. interface IWeapon
  50. {
  51. void Fire();
  52. }
  53. interface ITank:IWeapon,IVehicle //胖接口
  54. {
  55. }
  56. class LightTank : ITank
  57. {
  58. public void Fire()
  59. {
  60. Console.WriteLine("Boom");
  61. }
  62. public void Run()
  63. {
  64. Console.WriteLine("Ka ka ka...");
  65. }
  66. }
  67. class MediumTank : ITank
  68. {
  69. public void Fire()
  70. {
  71. Console.WriteLine("Medium Boom");
  72. }
  73. public void Run()
  74. {
  75. Console.WriteLine("Ka!ka! ka!...");
  76. }
  77. }
  78. class HeavyTank : ITank
  79. {
  80. public void Fire()
  81. {
  82. Console.WriteLine("Heavy Boom");
  83. }
  84. public void Run()
  85. {
  86. Console.WriteLine("Ka!! ka!! ka!!...");
  87. }
  88. }
  89. }

依赖注入Dependency injection(DI)应用

借助依赖注入框架:NuGet Package Manager—Dependency injection—Microsoft.Extensions.DenpendencyInjection.

  1. using System;
  2. using System.Reflection;
  3. using Microsoft.Extensions.DependencyInjection;
  4. namespace ISP_InterfaceSegregationPrinciple_
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. //容器,向容器要的时候new一个还是单例模式给同一个
  11. var sc = new ServiceCollection();
  12. sc.AddScoped(typeof(ITank), typeof(HeavyTank));//一对类型放进了容器
  13. var sp = sc.BuildServiceProvider();
  14. // ======== 华丽的分割线 =======
  15. ITank tank = sp.GetService<ITank>();
  16. tank.Fire();
  17. tank.Run();
  18. }
  19. }
  20. class Driver
  21. {
  22. private IVehicle _vehicle;
  23. public Driver(IVehicle vehicle)
  24. {
  25. _vehicle = vehicle;
  26. }
  27. public void Drive()
  28. {
  29. _vehicle.Run();
  30. }
  31. }
  32. interface IVehicle
  33. {
  34. void Run();
  35. }
  36. class Car : IVehicle
  37. {
  38. public void Run()
  39. {
  40. Console.WriteLine("Car is runnning");
  41. }
  42. }
  43. class Truck : IVehicle
  44. {
  45. public void Run()
  46. {
  47. Console.WriteLine("Truck is runnning");
  48. }
  49. }
  50. interface IWeapon
  51. {
  52. void Fire();
  53. }
  54. interface ITank:IWeapon,IVehicle //胖接口
  55. {
  56. }
  57. class LightTank : ITank
  58. {
  59. public void Fire()
  60. {
  61. Console.WriteLine("Boom");
  62. }
  63. public void Run()
  64. {
  65. Console.WriteLine("Ka ka ka...");
  66. }
  67. }
  68. class MediumTank : ITank
  69. {
  70. public void Fire()
  71. {
  72. Console.WriteLine("Medium Boom");
  73. }
  74. public void Run()
  75. {
  76. Console.WriteLine("Ka!ka! ka!...");
  77. }
  78. }
  79. class HeavyTank : ITank
  80. {
  81. public void Fire()
  82. {
  83. Console.WriteLine("Heavy Boom");
  84. }
  85. public void Run()
  86. {
  87. Console.WriteLine("Ka!! ka!! ka!!...");
  88. }
  89. }
  90. }

依赖链

注入到构造器中

  1. using System;
  2. using System.Reflection;
  3. using Microsoft.Extensions.DependencyInjection;
  4. namespace ISP_InterfaceSegregationPrinciple_
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. //容器,向容器要的时候new一个还是单例模式给同一个
  11. var sc = new ServiceCollection();
  12. sc.AddScoped(typeof(ITank), typeof(HeavyTank));//一对类型放进了容器
  13. sc.AddScoped(typeof(IVehicle), typeof(Car));//另一对类型放进了容器
  14. sc.AddScoped<Driver>();//放一个Driver进入到容器中
  15. var sp = sc.BuildServiceProvider();
  16. // ======== 华丽的分割线 =======
  17. ITank tank = sp.GetService<ITank>();
  18. tank.Fire();
  19. tank.Run();
  20. var driver = sp.GetService<Driver>();//找是否有Driver这个实例,找到后继续查找
  21. //是否有构造器里面需要的IVehicle,有,IVehicle绑定的是Car,则Driver驾驶Car
  22. driver.Drive();//依赖链
  23. }
  24. }
  25. class Driver
  26. {
  27. private IVehicle _vehicle;
  28. public Driver(IVehicle vehicle)
  29. {
  30. _vehicle = vehicle;
  31. }
  32. public void Drive()
  33. {
  34. _vehicle.Run();
  35. }
  36. }
  37. interface IVehicle
  38. {
  39. void Run();
  40. }
  41. class Car : IVehicle
  42. {
  43. public void Run()
  44. {
  45. Console.WriteLine("Car is runnning");
  46. }
  47. }
  48. class Truck : IVehicle
  49. {
  50. public void Run()
  51. {
  52. Console.WriteLine("Truck is runnning");
  53. }
  54. }
  55. interface IWeapon
  56. {
  57. void Fire();
  58. }
  59. interface ITank:IWeapon,IVehicle //胖接口
  60. {
  61. }
  62. class LightTank : ITank
  63. {
  64. public void Fire()
  65. {
  66. Console.WriteLine("Boom");
  67. }
  68. public void Run()
  69. {
  70. Console.WriteLine("Ka ka ka...");
  71. }
  72. }
  73. class MediumTank : ITank
  74. {
  75. public void Fire()
  76. {
  77. Console.WriteLine("Medium Boom");
  78. }
  79. public void Run()
  80. {
  81. Console.WriteLine("Ka!ka! ka!...");
  82. }
  83. }
  84. class HeavyTank : ITank
  85. {
  86. public void Fire()
  87. {
  88. Console.WriteLine("Heavy Boom");
  89. }
  90. public void Run()
  91. {
  92. Console.WriteLine("Ka!! ka!! ka!!...");
  93. }
  94. }
  95. }

反射—更松的耦合

更松的耦合一般应用在插件式编程。插件:不与主体程序一起编译,但可以与主体程序一起工作的组件,第三方来提供。以主体程序为中心,变成一个生态圈。
SDK里面的API来约束一下开发者,避免犯不必要的错误。

3 特性

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

3.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. }

3.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. ## 3.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. }