PageRenderTime 63ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/src/AutoMapper/Internal/FormatterExpression.cs

https://github.com/manzhyk/AutoMapper
C# | 227 lines | 184 code | 43 blank | 0 comment | 15 complexity | a246ce96c03ffff7bcd0eea0bf477009 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text.RegularExpressions;
  5. namespace AutoMapper
  6. {
  7. internal class FormatterExpression : IFormatterExpression, IFormatterConfiguration, IFormatterCtorConfigurator, IMappingOptions
  8. {
  9. private readonly Func<Type, IValueFormatter> _formatterCtor;
  10. private readonly IList<IValueFormatter> _formatters = new List<IValueFormatter>();
  11. private readonly IDictionary<Type, IFormatterConfiguration> _typeSpecificFormatters = new Dictionary<Type, IFormatterConfiguration>();
  12. private readonly IList<Type> _formattersToSkip = new List<Type>();
  13. private static readonly Func<string, string, string> PrefixFunc = (src, prefix) => Regex.Replace(src, string.Format("(?:^{0})?(.*)", prefix), "$1");
  14. private static readonly Func<string, string, string> PostfixFunc = (src, prefix) => Regex.Replace(src, string.Format("(.*)(?:{0})$", prefix), "$1");
  15. private static readonly Func<string, string, string, string> AliasFunc = (src, original, alias) => Regex.Replace(src, string.Format("^({0})$", original), alias);
  16. public FormatterExpression(Func<Type, IValueFormatter> formatterCtor)
  17. {
  18. _formatterCtor = formatterCtor;
  19. SourceMemberNamingConvention = new PascalCaseNamingConvention();
  20. DestinationMemberNamingConvention = new PascalCaseNamingConvention();
  21. SourceMemberNameTransformer = s => Regex.Replace(s, "(?:^Get)?(.*)", "$1");
  22. DestinationMemberNameTransformer = s => s;
  23. AllowNullDestinationValues = true;
  24. }
  25. public bool AllowNullDestinationValues { get; set; }
  26. public INamingConvention SourceMemberNamingConvention { get; set; }
  27. public INamingConvention DestinationMemberNamingConvention { get; set; }
  28. public Func<string, string> SourceMemberNameTransformer { get; set; }
  29. public Func<string, string> DestinationMemberNameTransformer { get; set; }
  30. public IFormatterCtorExpression<TValueFormatter> AddFormatter<TValueFormatter>() where TValueFormatter : IValueFormatter
  31. {
  32. var formatter = new DeferredInstantiatedFormatter(BuildCtor(typeof(TValueFormatter)));
  33. AddFormatter(formatter);
  34. return new FormatterCtorExpression<TValueFormatter>(this);
  35. }
  36. public IFormatterCtorExpression AddFormatter(Type valueFormatterType)
  37. {
  38. var formatter = new DeferredInstantiatedFormatter(BuildCtor(valueFormatterType));
  39. AddFormatter(formatter);
  40. return new FormatterCtorExpression(valueFormatterType, this);
  41. }
  42. public void AddFormatter(IValueFormatter valueFormatter)
  43. {
  44. _formatters.Add(valueFormatter);
  45. }
  46. public void AddFormatExpression(Func<ResolutionContext, string> formatExpression)
  47. {
  48. _formatters.Add(new ExpressionValueFormatter(formatExpression));
  49. }
  50. public void SkipFormatter<TValueFormatter>() where TValueFormatter : IValueFormatter
  51. {
  52. _formattersToSkip.Add(typeof(TValueFormatter));
  53. }
  54. public IFormatterExpression ForSourceType<TSource>()
  55. {
  56. var valueFormatter = new FormatterExpression(_formatterCtor);
  57. _typeSpecificFormatters[typeof (TSource)] = valueFormatter;
  58. return valueFormatter;
  59. }
  60. public IValueFormatter[] GetFormatters()
  61. {
  62. return _formatters.ToArray();
  63. }
  64. public IDictionary<Type, IFormatterConfiguration> GetTypeSpecificFormatters()
  65. {
  66. return new Dictionary<Type, IFormatterConfiguration>(_typeSpecificFormatters);
  67. }
  68. public Type[] GetFormatterTypesToSkip()
  69. {
  70. return _formattersToSkip.ToArray();
  71. }
  72. public IEnumerable<IValueFormatter> GetFormattersToApply(ResolutionContext context)
  73. {
  74. return GetFormatters(context);
  75. }
  76. private IEnumerable<IValueFormatter> GetFormatters(ResolutionContext context)
  77. {
  78. Type valueType = context.SourceType;
  79. IFormatterConfiguration typeSpecificFormatterConfig;
  80. if (context.PropertyMap != null)
  81. {
  82. foreach (IValueFormatter formatter in context.PropertyMap.GetFormatters())
  83. {
  84. yield return formatter;
  85. }
  86. if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig))
  87. {
  88. if (!context.PropertyMap.FormattersToSkipContains(typeSpecificFormatterConfig.GetType()))
  89. {
  90. foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context))
  91. {
  92. yield return typeSpecificFormatter;
  93. }
  94. }
  95. }
  96. }
  97. else if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig))
  98. {
  99. foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context))
  100. {
  101. yield return typeSpecificFormatter;
  102. }
  103. }
  104. foreach (IValueFormatter formatter in GetFormatters())
  105. {
  106. Type formatterType = GetFormatterType(formatter, context);
  107. if (CheckPropertyMapSkipList(context, formatterType) &&
  108. CheckTypeSpecificSkipList(typeSpecificFormatterConfig, formatterType))
  109. {
  110. yield return formatter;
  111. }
  112. }
  113. }
  114. public void ConstructFormatterBy(Type formatterType, Func<IValueFormatter> instantiator)
  115. {
  116. _formatters.RemoveAt(_formatters.Count - 1);
  117. _formatters.Add(new DeferredInstantiatedFormatter(ctxt => instantiator()));
  118. }
  119. public bool MapNullSourceValuesAsNull
  120. {
  121. get { return AllowNullDestinationValues; }
  122. }
  123. public void RecognizePrefixes(params string[] prefixes)
  124. {
  125. var orig = SourceMemberNameTransformer;
  126. SourceMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc);
  127. }
  128. public void RecognizePostfixes(params string[] postfixes)
  129. {
  130. var orig = SourceMemberNameTransformer;
  131. SourceMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc);
  132. }
  133. public void RecognizeAlias(string original, string alias)
  134. {
  135. var orig = SourceMemberNameTransformer;
  136. SourceMemberNameTransformer = val => AliasFunc(orig(val), original, alias);
  137. }
  138. public void RecognizeDestinationPrefixes(params string[] prefixes)
  139. {
  140. var orig = DestinationMemberNameTransformer;
  141. DestinationMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc);
  142. }
  143. public void RecognizeDestinationPostfixes(params string[] postfixes)
  144. {
  145. var orig = DestinationMemberNameTransformer;
  146. DestinationMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc);
  147. }
  148. private static Type GetFormatterType(IValueFormatter formatter, ResolutionContext context)
  149. {
  150. return formatter is DeferredInstantiatedFormatter ? ((DeferredInstantiatedFormatter)formatter).GetFormatterType(context) : formatter.GetType();
  151. }
  152. private static bool CheckTypeSpecificSkipList(IFormatterConfiguration valueFormatter, Type formatterType)
  153. {
  154. if (valueFormatter == null)
  155. {
  156. return true;
  157. }
  158. return !valueFormatter.GetFormatterTypesToSkip().Contains(formatterType);
  159. }
  160. private static bool CheckPropertyMapSkipList(ResolutionContext context, Type formatterType)
  161. {
  162. if (context.PropertyMap == null)
  163. return true;
  164. return !context.PropertyMap.FormattersToSkipContains(formatterType);
  165. }
  166. private Func<ResolutionContext, IValueFormatter> BuildCtor(Type type)
  167. {
  168. return context =>
  169. {
  170. if (context.Options.ServiceCtor != null)
  171. {
  172. var obj = context.Options.ServiceCtor(type);
  173. if (obj != null)
  174. return (IValueFormatter)obj;
  175. }
  176. return (IValueFormatter)_formatterCtor(type);
  177. };
  178. }
  179. }
  180. internal interface IFormatterCtorConfigurator
  181. {
  182. void ConstructFormatterBy(Type formatterType, Func<IValueFormatter> instantiator);
  183. }
  184. }