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.

151 lines
4.8 KiB

8 months ago
  1. using Dapper;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. namespace Mirle.Component.Database
  7. {
  8. /// <summary>
  9. /// Uses the Name value of the <see cref="ColumnAttribute"/> specified to determine
  10. /// the association between the name of the column in the query results and the member to
  11. /// which it will be extracted. If no column mapping is present all members are mapped as
  12. /// usual.
  13. /// </summary>
  14. /// <typeparam name="T">The type of the object that this association between the mapper applies to.</typeparam>
  15. public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
  16. {
  17. /// <summary>
  18. /// 建構式
  19. /// </summary>
  20. public ColumnAttributeTypeMapper()
  21. : base(new SqlMapper.ITypeMap[]
  22. {
  23. new CustomPropertyTypeMap(
  24. typeof(T),
  25. (type, columnName) =>
  26. type.GetProperties().ToList().Find(prop =>
  27. prop.GetCustomAttributes(false)
  28. .OfType<ColumnAttribute>()
  29. .Any(attr => attr.Name == columnName)
  30. )
  31. ),
  32. new DefaultTypeMap(typeof(T))
  33. })
  34. {
  35. }
  36. }
  37. /// <summary>
  38. /// 欄位屬性類別
  39. /// </summary>
  40. [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
  41. public class ColumnAttribute : Attribute
  42. {
  43. /// <summary>
  44. /// 欄位名稱
  45. /// </summary>
  46. public string Name { get; set; }
  47. }
  48. /// <summary>
  49. /// 欄位成員對應類別
  50. /// </summary>
  51. public class FallbackTypeMapper : SqlMapper.ITypeMap
  52. {
  53. private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
  54. /// <summary>
  55. /// 建構式
  56. /// </summary>
  57. /// <param name="mappers"></param>
  58. public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
  59. {
  60. _mappers = mappers;
  61. }
  62. /// <summary>
  63. ///
  64. /// </summary>
  65. /// <param name="names"></param>
  66. /// <param name="types"></param>
  67. /// <returns></returns>
  68. /// <exception cref="NotImplementedException"></exception>
  69. public ConstructorInfo FindConstructor(string[] names, Type[] types)
  70. {
  71. foreach (var mapper in _mappers)
  72. {
  73. try
  74. {
  75. ConstructorInfo result = mapper.FindConstructor(names, types);
  76. if (result != null)
  77. {
  78. return result;
  79. }
  80. }
  81. catch (NotImplementedException)
  82. {
  83. throw new NotImplementedException();
  84. }
  85. }
  86. return null;
  87. }
  88. /// <summary>
  89. ///
  90. /// </summary>
  91. /// <param name="constructor"></param>
  92. /// <param name="columnName"></param>
  93. /// <returns></returns>
  94. /// <exception cref="NotImplementedException"></exception>
  95. public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
  96. {
  97. foreach (var mapper in _mappers)
  98. {
  99. try
  100. {
  101. var result = mapper.GetConstructorParameter(constructor, columnName);
  102. if (result != null)
  103. {
  104. return result;
  105. }
  106. }
  107. catch (NotImplementedException)
  108. {
  109. throw new NotImplementedException();
  110. }
  111. }
  112. return null;
  113. }
  114. /// <summary>
  115. ///
  116. /// </summary>
  117. /// <param name="columnName"></param>
  118. /// <returns></returns>
  119. /// <exception cref="NotImplementedException"></exception>
  120. public SqlMapper.IMemberMap GetMember(string columnName)
  121. {
  122. foreach (var mapper in _mappers)
  123. {
  124. try
  125. {
  126. var result = mapper.GetMember(columnName);
  127. if (result != null)
  128. {
  129. return result;
  130. }
  131. }
  132. catch (NotImplementedException)
  133. {
  134. throw new NotImplementedException();
  135. }
  136. }
  137. return null;
  138. }
  139. /// <summary>
  140. ///
  141. /// </summary>
  142. /// <returns></returns>
  143. public ConstructorInfo FindExplicitConstructor()
  144. {
  145. return _mappers
  146. .Select(mapper => mapper.FindExplicitConstructor())
  147. .FirstOrDefault(result => result != null);
  148. }
  149. }
  150. }