diff options
| author | crupest <crupest@outlook.com> | 2022-12-06 21:03:36 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2022-12-20 20:32:52 +0800 | 
| commit | 4ac4c605e0602b1ef0d39c1fdcc42ebd880e10fd (patch) | |
| tree | 7dd05378a17e6b687af4987fe50e425171f0e07b /docker | |
| parent | e7532ff541de35bb02fa6f8305453cfb77cfc538 (diff) | |
| download | crupest-4ac4c605e0602b1ef0d39c1fdcc42ebd880e10fd.tar.gz crupest-4ac4c605e0602b1ef0d39c1fdcc42ebd880e10fd.tar.bz2 crupest-4ac4c605e0602b1ef0d39c1fdcc42ebd880e10fd.zip  | |
Develop secret api. v16
Diffstat (limited to 'docker')
5 files changed, 134 insertions, 235 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs index 1754c8d..081071f 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnInfo.cs @@ -20,11 +20,11 @@ public class ColumnInfo      }      // A column with no property. -    public ColumnInfo(Type entityType, string sqlColumnName, bool isPrimaryKey, bool isAutoIncrement, IColumnTypeInfo typeInfo, ColumnIndexType indexType = ColumnIndexType.None, ColumnTypeInfoRegistry? typeRegistry = null) +    public ColumnInfo(Type entityType, string sqlColumnName, bool isPrimaryKey, bool isAutoIncrement, ColumnTypeInfo typeInfo, ColumnIndexType indexType = ColumnIndexType.None, ColumnTypeRegistry? typeRegistry = null)      {          if (typeRegistry is null)          { -            typeRegistry = ColumnTypeInfoRegistry.Singleton; +            typeRegistry = ColumnTypeRegistry.Instance;          }          EntityType = entityType; @@ -40,11 +40,11 @@ public class ColumnInfo          IndexType = indexType;      } -    public ColumnInfo(Type entityType, string entityPropertyName, ColumnTypeInfoRegistry? typeRegistry = null) +    public ColumnInfo(Type entityType, string entityPropertyName, ColumnTypeRegistry? typeRegistry = null)      {          if (typeRegistry is null)          { -            typeRegistry = ColumnTypeInfoRegistry.Singleton; +            typeRegistry = ColumnTypeRegistry.Instance;          }          EntityType = entityType; @@ -73,25 +73,8 @@ public class ColumnInfo              DefaultEmptyForString = columnAttribute.DefaultEmptyForString;          } -        ColumnTypeInfo = typeRegistry.GetRequiredByDataType(PropertyRealType); +        ColumnTypeInfo = typeRegistry.GetRequired(PropertyRealType);          TypeRegistry = typeRegistry; - -        if (DefaultEmptyForString) -        { -            EntityPostGet += (entity, column, _, _) => -            { -                var pi = column.PropertyInfo; -                if (pi is not null && column.ColumnTypeInfo.GetUnderlineType() == typeof(string)) -                { -                    var value = pi.GetValue(entity); -                    if (value is null) -                    { -                        pi.SetValue(entity, string.Empty); -                    } -                } -                return Task.CompletedTask; -            }; -        }      }      public Type EntityType { get; } @@ -101,18 +84,17 @@ public class ColumnInfo      public Type PropertyType { get; }      public Type PropertyRealType { get; }      public string SqlColumnName { get; } -    public ColumnTypeInfoRegistry TypeRegistry { get; set; } -    public IColumnTypeInfo ColumnTypeInfo { get; } +    public ColumnTypeRegistry TypeRegistry { get; set; } +    public ColumnTypeInfo ColumnTypeInfo { get; }      public bool Nullable { get; }      public bool IsPrimaryKey { get; }      public bool IsAutoIncrement { get; }      public ColumnIndexType IndexType { get; } -    public bool DefaultEmptyForString { get; } -    public event EntityPreSave? EntityPreSave; -    public event EntityPostGet? EntityPostGet; +    // TODO: Implement this behavior. +    public bool DefaultEmptyForString { get; } -    public string SqlType => TypeRegistry.GetSqlTypeRecursive(ColumnTypeInfo); +    public string SqlType => ColumnTypeInfo.SqlType;      public string GenerateCreateTableColumnString()      { diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs index e39be98..4e640ff 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/ColumnTypeInfo.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic;  using System.Data;  using System.Diagnostics;  using System.Text.Json; @@ -5,157 +6,148 @@ using System.Text.Json.Serialization;  namespace CrupestApi.Commons.Crud; -public interface IColumnTypeInfo +/// <summary> Represents a type of one column. </summary> +public abstract class ColumnTypeInfo  { -    JsonConverter? GetOptionalJsonConverter() +    protected ColumnTypeInfo(Type supportedType)      { -        return null; +        SupportedType = supportedType;      } -    Type GetPropertyType(); -    Type GetUnderlineType(); -    object ConvertToUnderline(object data); -    object ConvertFromUnderline(object databaseData); +    public Type SupportedType { get; } -    void Validate(IReadOnlyDictionary<Type, IColumnTypeInfo> typeInfoMap) +    public bool IsOfSupportedType(object value)      { -        var typeSet = new HashSet<Type>(); +        return value is not null && SupportedType.IsAssignableFrom(value.GetType()); +    } -        IColumnTypeInfo current = this; +    public abstract BasicColumnTypeInfo UnderlineType { get; } -        while (current is not IBuiltinColumnTypeInfo) -        { -            var dataType = GetPropertyType(); +    public abstract IReadOnlyList<DerivedColumnTypeInfo> DerivedTypes { get; } -            if (typeSet.Contains(dataType)) -            { -                throw new Exception("Circular reference detected."); -            } -            typeSet.Add(dataType); +    public abstract string SqlType { get; } -            var databaseType = GetUnderlineType(); -            if (!typeInfoMap.ContainsKey(databaseType)) -            { -                throw new Exception("Broken type chain."); -            } +    public abstract DbType DbType { get; } -            current = typeInfoMap[databaseType]; -        } -    } -} +    /// <summary> +    /// An optional json converter for this type. +    /// </summary> +    /// <returns>The converter if this type needs a json converter. Otherwise null.</returns> +    public abstract JsonConverter? GetJsonConverter(); -public interface IBuiltinColumnTypeInfo : IColumnTypeInfo -{ -    /// To use for non-builtin type, use <see cref="ColumnTypeInfoRegistry.GetSqlTypeRecursive(IColumnTypeInfo)" /> because we need registry to query more information.  -    string GetSqlType(); -    // To use for non-builtin type, use <see cref="ColumnTypeInfoRegistry.GetDbType(IColumnTypeInfo)" /> because we need registry to query more information. -    DbType GetDbType(); +    /// <summary> +    /// Convert a value into underline type.  +    /// </summary> +    public abstract object? ConvertToUnderline(object? value); + +    /// <summary> +    /// Convert to a value of this type from value of underline type. +    /// </summary> +    public abstract object? ConvertFromUnderline(object? underlineValue);  } -public class BuiltinColumnTypeInfo<T> : IBuiltinColumnTypeInfo +public class BasicColumnTypeInfo : ColumnTypeInfo  { +    public static BasicColumnTypeInfo<char> CharColumnTypeInfo { get; } = new BasicColumnTypeInfo<char>("INTEGER", DbType.Int32); +    public static BasicColumnTypeInfo<short> ShortColumnTypeInfo { get; } = new BasicColumnTypeInfo<short>("INTEGER", DbType.Int32); +    public static BasicColumnTypeInfo<int> IntColumnTypeInfo { get; } = new BasicColumnTypeInfo<int>("INTEGER", DbType.Int32); +    public static BasicColumnTypeInfo<long> LongColumnTypeInfo { get; } = new BasicColumnTypeInfo<long>("INTEGER", DbType.Int64); +    public static BasicColumnTypeInfo<float> FloatColumnTypeInfo { get; } = new BasicColumnTypeInfo<float>("REAL", DbType.Double); +    public static BasicColumnTypeInfo<double> DoubleColumnTypeInfo { get; } = new BasicColumnTypeInfo<double>("REAL", DbType.Double); +    public static BasicColumnTypeInfo<string> StringColumnTypeInfo { get; } = new BasicColumnTypeInfo<string>("TEXT", DbType.String); +    public static BasicColumnTypeInfo<byte[]> ByteColumnTypeInfo { get; } = new BasicColumnTypeInfo<byte[]>("BLOB", DbType.Binary); +      private readonly string _sqlType;      private readonly DbType _dbType; +    internal List<DerivedColumnTypeInfo> _derivedTypes = new List<DerivedColumnTypeInfo>(); -    public BuiltinColumnTypeInfo(string sqlType, DbType dbType) +    public BasicColumnTypeInfo(Type type, string sqlType, DbType dbType) +    : base(type)      {          _sqlType = sqlType;          _dbType = dbType;      } -    public Type GetPropertyType() -    { -        return typeof(T); -    } +    public override BasicColumnTypeInfo UnderlineType => this; -    public Type GetUnderlineType() -    { -        return typeof(T); -    } - -    public string GetSqlType() -    { -        return _sqlType; -    } +    public override IReadOnlyList<DerivedColumnTypeInfo> DerivedTypes => _derivedTypes; -    public DbType GetDbType() -    { -        return _dbType; -    } +    public override string SqlType => _sqlType; -    public T ConvertToDatabase(T data) -    { -        return data; -    } +    public override DbType DbType => _dbType; -    public T ConvertFromDatabase(T databaseData) +    public override object? ConvertToUnderline(object? value)      { -        return databaseData; +        Debug.Assert(value is null || SupportedType.IsInstanceOfType(value)); +        return value;      } -    object IColumnTypeInfo.ConvertToUnderline(object data) +    public override object? ConvertFromUnderline(object? underlineValue)      { -        return data; +        Debug.Assert(underlineValue is null || SupportedType.IsInstanceOfType(underlineValue)); +        return underlineValue;      } -    object IColumnTypeInfo.ConvertFromUnderline(object databaseData) +    public override JsonConverter? GetJsonConverter()      { -        return databaseData; +        return null;      }  } -public interface ICustomColumnTypeInfo : IColumnTypeInfo +public class BasicColumnTypeInfo<T> : BasicColumnTypeInfo  { - +    public BasicColumnTypeInfo(string sqlType, DbType dbType) : base(typeof(T), sqlType, dbType) { }  } -public abstract class CustomColumnTypeInfo<TPropertyType, TUnderlineType> : ICustomColumnTypeInfo - where TPropertyType : notnull where TUnderlineType : notnull +public abstract class DerivedColumnTypeInfo : ColumnTypeInfo  { - -    public Type GetPropertyType() +    protected DerivedColumnTypeInfo(Type supportedType, BasicColumnTypeInfo underlineType) +        : base(supportedType)      { -        return typeof(TPropertyType); +        UnderlineType = underlineType; +        UnderlineType._derivedTypes.Add(this);      } -    public Type GetUnderlineType() -    { -        return typeof(TUnderlineType); -    } +    public override BasicColumnTypeInfo UnderlineType { get; } -    public abstract TUnderlineType ConvertToUnderline(TPropertyType data); -    public abstract TPropertyType ConvertFromUnderline(TUnderlineType databaseData); +    private static readonly List<DerivedColumnTypeInfo> _emptyList = new List<DerivedColumnTypeInfo>(); -    object IColumnTypeInfo.ConvertToUnderline(object data) -    { -        Debug.Assert(data is TPropertyType); -        return ConvertToUnderline((TPropertyType)data); -    } +    public override IReadOnlyList<DerivedColumnTypeInfo> DerivedTypes => _emptyList; -    object IColumnTypeInfo.ConvertFromUnderline(object databaseData) -    { -        Debug.Assert(databaseData is TUnderlineType); -        return ConvertFromUnderline((TUnderlineType)databaseData); -    } +    public override string SqlType => UnderlineType!.SqlType; + +    public override DbType DbType => UnderlineType!.DbType;  } -public class DateTimeColumnTypeInfo : CustomColumnTypeInfo<DateTime, long> +public class DateTimeColumnTypeInfo : DerivedColumnTypeInfo  {      private readonly DateTimeJsonConverter _jsonConverter = new DateTimeJsonConverter(); -    public JsonConverter GetJsonConverter() +    public DateTimeColumnTypeInfo() +        : base(typeof(DateTime), BasicColumnTypeInfo.LongColumnTypeInfo) +    { + +    } + +    public override JsonConverter GetJsonConverter()      {          return _jsonConverter;      } -    public override long ConvertToUnderline(DateTime data) +    public override object? ConvertToUnderline(object? value)      { -        return new DateTimeOffset(data).ToUnixTimeSeconds(); +        if (value is null) return null; + +        Debug.Assert(value is DateTime); +        return new DateTimeOffset((DateTime)value).ToUnixTimeSeconds();      } -    public override DateTime ConvertFromUnderline(long databaseData) +    public override object? ConvertFromUnderline(object? underlineValue)      { -        return DateTimeOffset.FromUnixTimeSeconds(databaseData).LocalDateTime; +        if (underlineValue is null) return null; + +        Debug.Assert(typeof(long).IsAssignableFrom(underlineValue.GetType())); +        return DateTimeOffset.FromUnixTimeSeconds((long)underlineValue).LocalDateTime;      }  } @@ -179,162 +171,87 @@ public class DateTimeJsonConverter : JsonConverter<DateTime>      }  } -public class ColumnTypeInfoRegistry +public class ColumnTypeRegistry  { -    public static IReadOnlyList<IColumnTypeInfo> BuiltinList = new List<IColumnTypeInfo>() -    { -        new BuiltinColumnTypeInfo<char>("INTEGER", DbType.Int32), -        new BuiltinColumnTypeInfo<short>("INTEGER", DbType.Int32), -        new BuiltinColumnTypeInfo<int>("INTEGER", DbType.Int32), -        new BuiltinColumnTypeInfo<long>("INTEGER", DbType.Int64), -        new BuiltinColumnTypeInfo<float>("REAL", DbType.Double), -        new BuiltinColumnTypeInfo<double>("REAL", DbType.Double), -        new BuiltinColumnTypeInfo<string>("TEXT", DbType.String), -        new BuiltinColumnTypeInfo<byte[]>("BLOB", DbType.Binary), -    }; - - -    public static IReadOnlyList<IColumnTypeInfo> CustomList = new List<IColumnTypeInfo>() -    { -        new DateTimeColumnTypeInfo(), +    public static IReadOnlyList<BasicColumnTypeInfo> BasicTypeList = new List<BasicColumnTypeInfo>() +    { +        BasicColumnTypeInfo.CharColumnTypeInfo, +        BasicColumnTypeInfo.ShortColumnTypeInfo, +        BasicColumnTypeInfo.IntColumnTypeInfo, +        BasicColumnTypeInfo.LongColumnTypeInfo, +        BasicColumnTypeInfo.FloatColumnTypeInfo, +        BasicColumnTypeInfo.DoubleColumnTypeInfo, +        BasicColumnTypeInfo.StringColumnTypeInfo, +        BasicColumnTypeInfo.ByteColumnTypeInfo,      }; -    public static ColumnTypeInfoRegistry Singleton { get; } +    public static ColumnTypeRegistry Instance { get; } -    static ColumnTypeInfoRegistry() +    static ColumnTypeRegistry()      { -        Singleton = new ColumnTypeInfoRegistry(); - -        foreach (var builtinColumnTypeInfo in BuiltinList) -        { -            Singleton.Register(builtinColumnTypeInfo); -        } +        Instance = new ColumnTypeRegistry(); -        foreach (var customColumnTypeInfo in CustomList) +        foreach (var basicColumnTypeInfo in BasicTypeList)          { -            Singleton.Register(customColumnTypeInfo); +            Instance.Register(basicColumnTypeInfo);          } -        Singleton.Validate(); +        Instance.Register(new DateTimeColumnTypeInfo());      } -    private readonly List<IColumnTypeInfo> _list; -    private readonly Dictionary<Type, IColumnTypeInfo> _map; -    private bool _dirty = false; +    private readonly List<ColumnTypeInfo> _list; +    private readonly Dictionary<Type, ColumnTypeInfo> _map; -    public ColumnTypeInfoRegistry() +    public ColumnTypeRegistry()      { -        _list = new List<IColumnTypeInfo>(); -        _map = new Dictionary<Type, IColumnTypeInfo>(); +        _list = new List<ColumnTypeInfo>(); +        _map = new Dictionary<Type, ColumnTypeInfo>();      } -    public void Register(IColumnTypeInfo columnTypeInfo) +    public void Register(ColumnTypeInfo columnTypeInfo)      {          Debug.Assert(!_list.Contains(columnTypeInfo)); +        Debug.Assert(!_map.ContainsKey(columnTypeInfo.SupportedType));          _list.Add(columnTypeInfo); -        _map.Add(columnTypeInfo.GetPropertyType(), columnTypeInfo); -        _dirty = true; +        _map.Add(columnTypeInfo.SupportedType, columnTypeInfo);      } -    public IColumnTypeInfo? GetByDataType(Type type) +    public ColumnTypeInfo? Get(Type type)      {          return _map.GetValueOrDefault(type);      } -    public IColumnTypeInfo GetRequiredByDataType(Type type) +    public ColumnTypeInfo? Get<T>()      { -        return GetByDataType(type) ?? throw new Exception("Unsupported type."); +        return Get(typeof(T));      } -    public string GetSqlTypeRecursive(IColumnTypeInfo columnTypeInfo) +    public ColumnTypeInfo GetRequired(Type type)      { -        EnsureValidity(); - -        IColumnTypeInfo? current = columnTypeInfo; -        while (current is not IBuiltinColumnTypeInfo) -        { -            current = GetByDataType(current.GetUnderlineType()); -            Debug.Assert(current is not null); -        } - -        return ((IBuiltinColumnTypeInfo)current).GetSqlType(); +        return Get(type) ?? throw new Exception("Unsupported type.");      } -    public DbType GetDbTypeRecursive(IColumnTypeInfo columnTypeInfo) +    public ColumnTypeInfo GetRequired<T>()      { -        EnsureValidity(); - -        IColumnTypeInfo? current = columnTypeInfo; -        if (current is not IBuiltinColumnTypeInfo) -        { -            current = GetByDataType(current.GetUnderlineType()); -            Debug.Assert(current is not null); -        } - -        return ((IBuiltinColumnTypeInfo)current).GetDbType(); -    } - -    public object? ConvertToUnderlineRecursive(object? value) -    { -        EnsureValidity(); - -        if (value is null) -        { -            return null; -        } - -        IColumnTypeInfo? current = GetByDataType(value.GetType()); -        if (current is null) -        { -            return value; -        } - -        while (current is not IBuiltinColumnTypeInfo) -        { -            value = current.ConvertToUnderline(value); -            current = GetByDataType(current.GetUnderlineType()); -            Debug.Assert(current is not null); -        } - -        return value; -    } - -    public string GetSqlType(Type type) -    { -        return GetSqlTypeRecursive(GetRequiredByDataType(type)); -    } - -    public DbType GetDbType(Type type) -    { -        return GetDbTypeRecursive(GetRequiredByDataType(type)); +        return GetRequired(typeof(T));      }      public object? ConvertToUnderline(object? value)      { -        return ConvertToUnderlineRecursive(value); -    } +        if (value is null) return null; -    public void Validate() -    { -        foreach (var columnTypeInfo in _list) -        { -            columnTypeInfo.Validate(_map); -        } -    } +        var type = value.GetType(); +        var columnTypeInfo = Get(type); +        if (columnTypeInfo is null) throw new Exception("Unsupported type."); -    public void EnsureValidity() -    { -        if (_dirty) -        { -            Validate(); -        } +        return columnTypeInfo.ConvertToUnderline(value);      }      public IEnumerable<JsonConverter> GetJsonConverters()      {          foreach (var columnTypeInfo in _list)          { -            var converter = columnTypeInfo.GetOptionalJsonConverter(); +            var converter = columnTypeInfo.GetJsonConverter();              if (converter is not null)                  yield return converter;          } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs index c58897c..ac02226 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/TableInfo.cs @@ -42,7 +42,7 @@ public class TableInfo          if (!hasPrimaryKey)          {              if (hasId) throw new Exception("A column named id already exists but is not primary key."); -            var columnInfo = new ColumnInfo(entityType, "id", true, true, ColumnTypeInfoRegistry.Singleton.GetRequiredByDataType(typeof(int))); +            var columnInfo = new ColumnInfo(entityType, "id", true, true, ColumnTypeRegistry.Instance.GetRequired<int>());              columnInfos.Add(columnInfo);          } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs index ba1a28c..26dc306 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Crud/WhereClause.cs @@ -57,7 +57,7 @@ public static class DynamicParametersExtensions      public static string AddRandomNameParameter(this DynamicParameters parameters, object? value)      {          var parameterName = IWhereClause.GenerateRandomParameterName(parameters); -        parameters.Add(parameterName, ColumnTypeInfoRegistry.Singleton.ConvertToUnderlineRecursive(value)); +        parameters.Add(parameterName, ColumnTypeRegistry.Instance.ConvertToUnderline(value));          return parameterName;      }  } diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Json.cs b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Json.cs index bbb6efe..76746b4 100644 --- a/docker/crupest-api/CrupestApi/CrupestApi.Commons/Json.cs +++ b/docker/crupest-api/CrupestApi/CrupestApi.Commons/Json.cs @@ -14,7 +14,7 @@ public static class CrupestApiJsonExtensions              config.AllowTrailingCommas = true;              config.PropertyNameCaseInsensitive = true;              config.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; -            foreach (var converter in ColumnTypeInfoRegistry.Singleton.GetJsonConverters()) +            foreach (var converter in ColumnTypeRegistry.Instance.GetJsonConverters())              {                  config.Converters.Add(converter);              }  | 
