You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
7.1 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. using Apewer.Internals;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using System.Text;
  6. namespace Apewer.Source
  7. {
  8. /// <summary>数据库中的列,类型默认为 NVarChar(191),错误类型将修正为默认类型。</summary>
  9. /// <remarks>注意:当一个数据模型中存在多个相同的 Field 时,将只有第一个被保留。</remarks>
  10. [Serializable]
  11. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  12. public sealed class ColumnAttribute : Attribute
  13. {
  14. private PropertyInfo _property = null;
  15. internal string PropertyName = null;
  16. private string _field = null;
  17. private int _length = 0;
  18. private ColumnType _type;
  19. private bool _independent = false;
  20. private bool _valid = true;
  21. private void Init(string field, ColumnType type, int length)
  22. {
  23. _field = field;
  24. _type = type;
  25. switch (type)
  26. {
  27. case ColumnType.VarChar:
  28. case ColumnType.NVarChar:
  29. _length = length < 1 ? 191 : length;
  30. break;
  31. case ColumnType.VarChar191:
  32. case ColumnType.NVarChar191:
  33. _length = 191;
  34. break;
  35. default:
  36. _length = length;
  37. break;
  38. }
  39. }
  40. /// <summary>使用自动的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。</summary>
  41. /// <exception cref="System.ArgumentOutOfRangeException"></exception>
  42. public ColumnAttribute(ColumnType type = ColumnType.NVarChar191, int length = 191) => Init(null, type, length);
  43. /// <summary>使用指定的列名称。当类型为 VarChar 或 NVarChar 时必须指定长度。</summary>
  44. /// <exception cref="System.ArgumentOutOfRangeException"></exception>
  45. public ColumnAttribute(string field, ColumnType type = ColumnType.NVarChar191, int length = 191) => Init(field, type, length);
  46. /// <summary>字段名。</summary>
  47. public string Field { get => _field; }
  48. /// <summary>指定字段的最大长度。</summary>
  49. public int Length { get => _length; }
  50. /// <summary>字段类型。</summary>
  51. public ColumnType Type { get => _type; }
  52. #region 附加
  53. /// <summary>此特性有效。</summary>
  54. public bool Valid { get => _valid; }
  55. /// <summary>Independent 特性。</summary>
  56. public bool Independent { get => _independent; }
  57. /// <summary>使用此特性的属性。</summary>
  58. public PropertyInfo Property { get => _property; }
  59. #endregion
  60. /// <summary>解析列特性。</summary>
  61. /// <remarks>注意:此方法不再抛出异常,当不存在正确的列特性时将返回 NULL 值</remarks>
  62. public static ColumnAttribute Parse(Type type, PropertyInfo property, TableAttribute ta)
  63. {
  64. if (type == null || property == null || ta == null) return null;
  65. // 属性带有 Independent 特性。
  66. if (property.Contains<IndependentAttribute>()) return null;
  67. // 检查 ColumnAttribute。
  68. ColumnAttribute ca;
  69. {
  70. var cas = property.GetCustomAttributes(typeof(ColumnAttribute), false);
  71. if (cas.LongLength < 1L)
  72. {
  73. if (!ta.AllProperties) return null;
  74. ca = new ColumnAttribute();
  75. }
  76. else ca = (ColumnAttribute)cas[0];
  77. }
  78. // 检查属性方法。
  79. var getter = property.GetGetMethod(false);
  80. var setter = property.GetSetMethod(false);
  81. if (getter == null || getter.IsStatic) return null;
  82. if (setter == null || setter.IsStatic) return null;
  83. // 检查列名称。
  84. if (TextUtility.IsBlank(ca.Field)) ca._field = property.Name;
  85. // 类型兼容。
  86. var pt = property.PropertyType;
  87. if (pt.Equals(typeof(byte[]).FullName)) ca._type = ColumnType.Bytes;
  88. else if (pt.Equals(typeof(Byte))) ca._type = ColumnType.Integer;
  89. else if (pt.Equals(typeof(SByte))) ca._type = ColumnType.Integer;
  90. else if (pt.Equals(typeof(Int16))) ca._type = ColumnType.Integer;
  91. else if (pt.Equals(typeof(UInt16))) ca._type = ColumnType.Integer;
  92. else if (pt.Equals(typeof(Int32))) ca._type = ColumnType.Integer;
  93. else if (pt.Equals(typeof(UInt32))) ca._type = ColumnType.Integer;
  94. else if (pt.Equals(typeof(Int64))) ca._type = ColumnType.Integer;
  95. else if (pt.Equals(typeof(Single))) ca._type = ColumnType.Float;
  96. else if (pt.Equals(typeof(Double))) ca._type = ColumnType.Float;
  97. else if (pt.Equals(typeof(Decimal))) ca._type = ColumnType.Float;
  98. else if (pt.Equals(typeof(DateTime))) ca._type = ColumnType.DateTime;
  99. else if (pt.Equals(typeof(String)))
  100. {
  101. switch (ca.Type)
  102. {
  103. case ColumnType.Bytes:
  104. case ColumnType.Integer:
  105. case ColumnType.Float:
  106. case ColumnType.DateTime:
  107. //throw new Exception(TextGenerator.Merge("类 ", type.FullName, " 中,属性 ", property.Name, " 的类型不受支持。"));
  108. ca._type = ColumnType.NVarChar;
  109. ca._length = 191;
  110. break;
  111. }
  112. }
  113. else
  114. {
  115. ca._type = ColumnType.NVarChar191;
  116. ca._length = 191;
  117. }
  118. ca._property = property;
  119. ca.PropertyName = property.Name;
  120. if (ca.PropertyName == "Key" || ca.PropertyName == "Flag") ca._independent = true;
  121. return ca;
  122. }
  123. /// <summary>对列特性排序,Key 和 Flag 将始终排在前部。</summary>
  124. public static ColumnAttribute[] Sort(ColumnAttribute[] columns, bool sort = false)
  125. {
  126. var total = columns.Length;
  127. var key = null as ColumnAttribute;
  128. var flag = null as ColumnAttribute;
  129. var temp = new List<ColumnAttribute>(total);
  130. for (var i = 0; i < total; i++)
  131. {
  132. var ca = columns[i];
  133. if (ca == null) continue;
  134. var pn = ca.Property.Name;
  135. if (pn == "Key") key = ca;
  136. else if (pn == "Flag") flag = ca;
  137. else temp.Add(ca);
  138. }
  139. if (sort && temp.Count > 0) temp.Sort((a, b) => a._field.CompareTo(b._field));
  140. if (key == null && flag == null) return temp.ToArray();
  141. total = 0;
  142. if (key != null) total += 1;
  143. if (flag != null) total += 1;
  144. total += temp.Count;
  145. var sorted = new List<ColumnAttribute>(total);
  146. if (key != null) sorted.Add(key);
  147. if (flag != null) sorted.Add(flag);
  148. sorted.AddRange(temp);
  149. return sorted.ToArray();
  150. }
  151. }
  152. }