TypeConverterBinder.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Globalization;
  5. namespace FastGithub.Configuration
  6. {
  7. /// <summary>
  8. /// TypeConverter类型转换绑定器
  9. /// </summary>
  10. static class TypeConverterBinder
  11. {
  12. private static readonly Dictionary<Type, Binder> binders = new();
  13. /// <summary>
  14. /// 绑定转换器到指定类型
  15. /// </summary>
  16. /// <typeparam name="T"></typeparam>
  17. /// <param name="reader"></param>
  18. /// <param name="writer"></param>
  19. public static void Bind<T>(Func<string, T?> reader, Func<T?, string?> writer)
  20. {
  21. binders[typeof(T)] = new Binder<T>(reader, writer);
  22. var converterType = typeof(TypeConverter<>).MakeGenericType(typeof(T));
  23. if (TypeDescriptor.GetConverter(typeof(T)).GetType() != converterType)
  24. {
  25. TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(converterType));
  26. }
  27. }
  28. private abstract class Binder
  29. {
  30. public abstract object? Read(string value);
  31. public abstract string? Write(object? value);
  32. }
  33. private class Binder<T> : Binder
  34. {
  35. private readonly Func<string, T?> reader;
  36. private readonly Func<T?, string?> writer;
  37. public Binder(Func<string, T?> reader, Func<T?, string?> writer)
  38. {
  39. this.reader = reader;
  40. this.writer = writer;
  41. }
  42. public override object? Read(string value)
  43. {
  44. return this.reader(value);
  45. }
  46. public override string? Write(object? value)
  47. {
  48. return this.writer((T?)value);
  49. }
  50. }
  51. private class TypeConverter<T> : TypeConverter
  52. {
  53. public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
  54. {
  55. return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
  56. }
  57. public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
  58. {
  59. if (value is string stringVal)
  60. {
  61. if (stringVal.Equals(string.Empty))
  62. {
  63. return default(T);
  64. }
  65. else if (binders.TryGetValue(typeof(T), out var binder))
  66. {
  67. return binder.Read(stringVal);
  68. }
  69. }
  70. return base.ConvertFrom(context, culture, value);
  71. }
  72. public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
  73. {
  74. return destinationType == typeof(T) && binders.TryGetValue(destinationType, out var binder)
  75. ? binder.Write(value)
  76. : base.ConvertTo(context, culture, value, destinationType);
  77. }
  78. }
  79. }
  80. }