Explorar el Código

add ValueBinder

陈国伟 hace 3 años
padre
commit
2d9f505634

+ 3 - 2
FastGithub.Configuration/DomainConfig.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Net;
 
 
 namespace FastGithub.Configuration
 namespace FastGithub.Configuration
 {
 {
@@ -26,7 +27,7 @@ namespace FastGithub.Configuration
         /// <summary>
         /// <summary>
         /// 使用的ip地址
         /// 使用的ip地址
         /// </summary>
         /// </summary>
-        public string? IPAddress { get; init; }
+        public IPAddress? IPAddress { get; init; }
 
 
         /// <summary>
         /// <summary>
         /// 请求超时时长
         /// 请求超时时长
@@ -59,6 +60,6 @@ namespace FastGithub.Configuration
                 return Configuration.TlsSniPattern.Domain;
                 return Configuration.TlsSniPattern.Domain;
             }
             }
             return new TlsSniPattern(this.TlsSniPattern);
             return new TlsSniPattern(this.TlsSniPattern);
-        }
+        } 
     }
     }
 }
 }

+ 2 - 18
FastGithub.Configuration/FastGithubConfig.cs

@@ -35,7 +35,7 @@ namespace FastGithub.Configuration
             var opt = options.CurrentValue;
             var opt = options.CurrentValue;
 
 
             this.HttpProxyPort = opt.HttpProxyPort;
             this.HttpProxyPort = opt.HttpProxyPort;
-            this.FallbackDns = ConvertToIPEndPoints(opt.FallbackDns).ToArray();
+            this.FallbackDns = opt.FallbackDns;
             this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs);
             this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs);
             this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
             this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
 
 
@@ -49,27 +49,11 @@ namespace FastGithub.Configuration
         private void Update(FastGithubOptions options)
         private void Update(FastGithubOptions options)
         {
         {
             this.HttpProxyPort = options.HttpProxyPort;
             this.HttpProxyPort = options.HttpProxyPort;
-            this.FallbackDns = ConvertToIPEndPoints(options.FallbackDns).ToArray();
+            this.FallbackDns = options.FallbackDns;
             this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs);
             this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs);
             this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
             this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
         }
         }
 
 
-        /// <summary>
-        /// 转换为IPEndPoint
-        /// </summary>
-        /// <param name="ipEndPoints"></param>
-        /// <returns></returns>
-        private static IEnumerable<IPEndPoint> ConvertToIPEndPoints(IEnumerable<string> ipEndPoints)
-        {
-            foreach (var item in ipEndPoints)
-            {
-                if (IPEndPoint.TryParse(item, out var endPoint))
-                {
-                    yield return endPoint;
-                }
-            }
-        }
-
         /// <summary>
         /// <summary>
         /// 配置转换
         /// 配置转换
         /// </summary>
         /// </summary>

+ 2 - 1
FastGithub.Configuration/FastGithubOptions.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Net;
 
 
 namespace FastGithub.Configuration
 namespace FastGithub.Configuration
 {
 {
@@ -16,7 +17,7 @@ namespace FastGithub.Configuration
         /// <summary>
         /// <summary>
         /// 回退的dns
         /// 回退的dns
         /// </summary>
         /// </summary>
-        public string[] FallbackDns { get; set; } = Array.Empty<string>();
+        public IPEndPoint[] FallbackDns { get; set; } = Array.Empty<IPEndPoint>();
 
 
         /// <summary>
         /// <summary>
         /// 代理的域名配置
         /// 代理的域名配置

+ 4 - 0
FastGithub.Configuration/ServiceCollectionExtensions.cs

@@ -2,6 +2,7 @@
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection.Extensions;
 using Microsoft.Extensions.DependencyInjection.Extensions;
 using Microsoft.Extensions.Options;
 using Microsoft.Extensions.Options;
+using System.Net;
 
 
 namespace FastGithub
 namespace FastGithub
 {
 {
@@ -17,6 +18,9 @@ namespace FastGithub
         /// <returns></returns>
         /// <returns></returns>
         public static IServiceCollection AddConfiguration(this IServiceCollection services)
         public static IServiceCollection AddConfiguration(this IServiceCollection services)
         {
         {
+            ValueBinder.Bind(val => IPAddress.Parse(val), val => val?.ToString());
+            ValueBinder.Bind(val => IPEndPoint.Parse(val), val => val?.ToString());
+
             services.TryAddSingleton<FastGithubConfig>();
             services.TryAddSingleton<FastGithubConfig>();
             return services;
             return services;
         }
         }

+ 85 - 0
FastGithub.Configuration/ValueBinder.cs

@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+
+namespace FastGithub.Configuration
+{
+    /// <summary>
+    /// 配置值绑定器
+    /// </summary>
+    static class ValueBinder
+    {
+        private static readonly Dictionary<Type, Binder> binders = new();
+
+        /// <summary>
+        /// 绑定转换器到指定类型
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="reader"></param>
+        /// <param name="writer"></param>
+        public static void Bind<T>(Func<string, T?> reader, Func<T?, string?> writer)
+        {
+            binders[typeof(T)] = new Binder<T>(reader, writer);
+
+            var converterType = typeof(TypeConverter<>).MakeGenericType(typeof(T));
+            if (TypeDescriptor.GetConverter(typeof(T)).GetType() != converterType)
+            {
+                TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(converterType));
+            }
+        }
+
+        private abstract class Binder
+        {
+            public abstract object? Read(string value);
+
+            public abstract string? Write(object? value);
+        }
+
+
+        private class Binder<T> : Binder
+        {
+            private readonly Func<string, T?> reader;
+            private readonly Func<T?, string?> writer;
+
+            public Binder(Func<string, T?> reader, Func<T?, string?> writer)
+            {
+                this.reader = reader;
+                this.writer = writer;
+            }
+
+            public override object? Read(string value)
+            {
+                return this.reader(value);
+            }
+
+            public override string? Write(object? value)
+            {
+                return this.writer((T?)value);
+            }
+        }
+
+
+        private class TypeConverter<T> : TypeConverter
+        {
+            public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+            {
+                return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
+            }
+
+            public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+            {
+                return value is string stringVal && binders.TryGetValue(typeof(T), out var binder)
+                    ? binder.Read(stringVal)
+                    : base.ConvertFrom(context, culture, value);
+            }
+
+            public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+            {
+                return destinationType == typeof(T) && binders.TryGetValue(destinationType, out var binder)
+                    ? binder.Write(value)
+                    : base.ConvertTo(context, culture, value, destinationType);
+            }
+        }
+    }
+}

+ 2 - 2
FastGithub.Http/HttpClientHandler.cs

@@ -181,9 +181,9 @@ namespace FastGithub.Http
             }
             }
             else
             else
             {
             {
-                if (IPAddress.TryParse(this.domainConfig.IPAddress, out address))
+                if (this.domainConfig.IPAddress != null)
                 {
                 {
-                    yield return new IPEndPoint(address, dnsEndPoint.Port);
+                    yield return new IPEndPoint(this.domainConfig.IPAddress, dnsEndPoint.Port);
                 }
                 }
 
 
                 await foreach (var item in this.domainResolver.ResolveAllAsync(dnsEndPoint, cancellationToken))
                 await foreach (var item in this.domainResolver.ResolveAllAsync(dnsEndPoint, cancellationToken))