From 18ff1b796193ee763ff77c0c4865ae6cae322e85 Mon Sep 17 00:00:00 2001 From: C-J Berg Date: Mon, 28 Nov 2011 00:04:13 +0100 Subject: [PATCH 1/2] Unified line-endings (was mixed) and used tabs for indenting (was mixed with spaces). --- .../Internal/FormatterExpression.cs | 464 +++++++++--------- 1 file changed, 232 insertions(+), 232 deletions(-) diff --git a/src/AutoMapper/Internal/FormatterExpression.cs b/src/AutoMapper/Internal/FormatterExpression.cs index e5b4ce1387..cb7ef6ad26 100644 --- a/src/AutoMapper/Internal/FormatterExpression.cs +++ b/src/AutoMapper/Internal/FormatterExpression.cs @@ -1,233 +1,233 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace AutoMapper -{ - internal class FormatterExpression : IFormatterExpression, IFormatterConfiguration, IFormatterCtorConfigurator, IMappingOptions - { - private readonly Func _formatterCtor; - private readonly IList _formatters = new List(); - private readonly IDictionary _typeSpecificFormatters = new Dictionary(); - private readonly IList _formattersToSkip = new List(); - private static readonly Func PrefixFunc = (src, prefix) => Regex.Replace(src, string.Format("(?:^{0})?(.*)", prefix), "$1"); - private static readonly Func PostfixFunc = (src, prefix) => Regex.Replace(src, string.Format("(.*)(?:{0})$", prefix), "$1"); - private static readonly Func AliasFunc = (src, original, alias) => Regex.Replace(src, string.Format("^({0})$", original), alias); - - public FormatterExpression(Func formatterCtor) - { - _formatterCtor = formatterCtor; - SourceMemberNamingConvention = new PascalCaseNamingConvention(); - DestinationMemberNamingConvention = new PascalCaseNamingConvention(); - SourceMemberNameTransformer = s => Regex.Replace(s, "(?:^Get)?(.*)", "$1"); - DestinationMemberNameTransformer = s => s; - AllowNullDestinationValues = true; - } - - public bool AllowNullDestinationValues { get; set; } - public bool AllowNullCollections { get; set; } - public INamingConvention SourceMemberNamingConvention { get; set; } - public INamingConvention DestinationMemberNamingConvention { get; set; } - public Func SourceMemberNameTransformer { get; set; } - public Func DestinationMemberNameTransformer { get; set; } - - public IFormatterCtorExpression AddFormatter() where TValueFormatter : IValueFormatter - { - var formatter = new DeferredInstantiatedFormatter(BuildCtor(typeof(TValueFormatter))); - - AddFormatter(formatter); - - return new FormatterCtorExpression(this); - } - - public IFormatterCtorExpression AddFormatter(Type valueFormatterType) - { - var formatter = new DeferredInstantiatedFormatter(BuildCtor(valueFormatterType)); - - AddFormatter(formatter); - - return new FormatterCtorExpression(valueFormatterType, this); - } - - public void AddFormatter(IValueFormatter valueFormatter) - { - _formatters.Add(valueFormatter); - } - - public void AddFormatExpression(Func formatExpression) - { - _formatters.Add(new ExpressionValueFormatter(formatExpression)); - } - - public void SkipFormatter() where TValueFormatter : IValueFormatter - { - _formattersToSkip.Add(typeof(TValueFormatter)); - } - - public IFormatterExpression ForSourceType() - { - var valueFormatter = new FormatterExpression(_formatterCtor); - - _typeSpecificFormatters[typeof (TSource)] = valueFormatter; - - return valueFormatter; - } - - public IValueFormatter[] GetFormatters() - { - return _formatters.ToArray(); - } - - public IDictionary GetTypeSpecificFormatters() - { - return new Dictionary(_typeSpecificFormatters); - } - - public Type[] GetFormatterTypesToSkip() - { - return _formattersToSkip.ToArray(); - } - - public IEnumerable GetFormattersToApply(ResolutionContext context) - { - return GetFormatters(context); - } - - private IEnumerable GetFormatters(ResolutionContext context) - { - Type valueType = context.SourceType; - IFormatterConfiguration typeSpecificFormatterConfig; - - if (context.PropertyMap != null) - { - foreach (IValueFormatter formatter in context.PropertyMap.GetFormatters()) - { - yield return formatter; - } - - if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig)) - { - if (!context.PropertyMap.FormattersToSkipContains(typeSpecificFormatterConfig.GetType())) - { - foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context)) - { - yield return typeSpecificFormatter; - } - } - } - } - else if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig)) - { - foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context)) - { - yield return typeSpecificFormatter; - } - } - - foreach (IValueFormatter formatter in GetFormatters()) - { - Type formatterType = GetFormatterType(formatter, context); - if (CheckPropertyMapSkipList(context, formatterType) && - CheckTypeSpecificSkipList(typeSpecificFormatterConfig, formatterType)) - { - yield return formatter; - } - } - } - - public void ConstructFormatterBy(Type formatterType, Func instantiator) - { - _formatters.RemoveAt(_formatters.Count - 1); - _formatters.Add(new DeferredInstantiatedFormatter(ctxt => instantiator())); - } - - public bool MapNullSourceValuesAsNull - { - get { return AllowNullDestinationValues; } - } - - public bool MapNullSourceCollectionsAsNull - { - get { return AllowNullCollections; } - } - - public void RecognizePrefixes(params string[] prefixes) - { - var orig = SourceMemberNameTransformer; - - SourceMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc); - } - - public void RecognizePostfixes(params string[] postfixes) - { - var orig = SourceMemberNameTransformer; - - SourceMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc); - } - - public void RecognizeAlias(string original, string alias) - { - var orig = SourceMemberNameTransformer; - - SourceMemberNameTransformer = val => AliasFunc(orig(val), original, alias); - } - - public void RecognizeDestinationPrefixes(params string[] prefixes) - { - var orig = DestinationMemberNameTransformer; - - DestinationMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc); - } - - public void RecognizeDestinationPostfixes(params string[] postfixes) - { - var orig = DestinationMemberNameTransformer; - - DestinationMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc); - } - - private static Type GetFormatterType(IValueFormatter formatter, ResolutionContext context) - { - return formatter is DeferredInstantiatedFormatter ? ((DeferredInstantiatedFormatter)formatter).GetFormatterType(context) : formatter.GetType(); - } - - private static bool CheckTypeSpecificSkipList(IFormatterConfiguration valueFormatter, Type formatterType) - { - if (valueFormatter == null) - { - return true; - } - - return !valueFormatter.GetFormatterTypesToSkip().Contains(formatterType); - } - - private static bool CheckPropertyMapSkipList(ResolutionContext context, Type formatterType) - { - if (context.PropertyMap == null) - return true; - - return !context.PropertyMap.FormattersToSkipContains(formatterType); - } - - private Func BuildCtor(Type type) - { - return context => - { - if (context.Options.ServiceCtor != null) - { - var obj = context.Options.ServiceCtor(type); - if (obj != null) - return (IValueFormatter)obj; - } - return (IValueFormatter)_formatterCtor(type); - }; - } - - } - - internal interface IFormatterCtorConfigurator - { - void ConstructFormatterBy(Type formatterType, Func instantiator); - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace AutoMapper +{ + internal class FormatterExpression : IFormatterExpression, IFormatterConfiguration, IFormatterCtorConfigurator, IMappingOptions + { + private readonly Func _formatterCtor; + private readonly IList _formatters = new List(); + private readonly IDictionary _typeSpecificFormatters = new Dictionary(); + private readonly IList _formattersToSkip = new List(); + private static readonly Func PrefixFunc = (src, prefix) => Regex.Replace(src, string.Format("(?:^{0})?(.*)", prefix), "$1"); + private static readonly Func PostfixFunc = (src, prefix) => Regex.Replace(src, string.Format("(.*)(?:{0})$", prefix), "$1"); + private static readonly Func AliasFunc = (src, original, alias) => Regex.Replace(src, string.Format("^({0})$", original), alias); + + public FormatterExpression(Func formatterCtor) + { + _formatterCtor = formatterCtor; + SourceMemberNamingConvention = new PascalCaseNamingConvention(); + DestinationMemberNamingConvention = new PascalCaseNamingConvention(); + SourceMemberNameTransformer = s => Regex.Replace(s, "(?:^Get)?(.*)", "$1"); + DestinationMemberNameTransformer = s => s; + AllowNullDestinationValues = true; + } + + public bool AllowNullDestinationValues { get; set; } + public bool AllowNullCollections { get; set; } + public INamingConvention SourceMemberNamingConvention { get; set; } + public INamingConvention DestinationMemberNamingConvention { get; set; } + public Func SourceMemberNameTransformer { get; set; } + public Func DestinationMemberNameTransformer { get; set; } + + public IFormatterCtorExpression AddFormatter() where TValueFormatter : IValueFormatter + { + var formatter = new DeferredInstantiatedFormatter(BuildCtor(typeof(TValueFormatter))); + + AddFormatter(formatter); + + return new FormatterCtorExpression(this); + } + + public IFormatterCtorExpression AddFormatter(Type valueFormatterType) + { + var formatter = new DeferredInstantiatedFormatter(BuildCtor(valueFormatterType)); + + AddFormatter(formatter); + + return new FormatterCtorExpression(valueFormatterType, this); + } + + public void AddFormatter(IValueFormatter valueFormatter) + { + _formatters.Add(valueFormatter); + } + + public void AddFormatExpression(Func formatExpression) + { + _formatters.Add(new ExpressionValueFormatter(formatExpression)); + } + + public void SkipFormatter() where TValueFormatter : IValueFormatter + { + _formattersToSkip.Add(typeof(TValueFormatter)); + } + + public IFormatterExpression ForSourceType() + { + var valueFormatter = new FormatterExpression(_formatterCtor); + + _typeSpecificFormatters[typeof (TSource)] = valueFormatter; + + return valueFormatter; + } + + public IValueFormatter[] GetFormatters() + { + return _formatters.ToArray(); + } + + public IDictionary GetTypeSpecificFormatters() + { + return new Dictionary(_typeSpecificFormatters); + } + + public Type[] GetFormatterTypesToSkip() + { + return _formattersToSkip.ToArray(); + } + + public IEnumerable GetFormattersToApply(ResolutionContext context) + { + return GetFormatters(context); + } + + private IEnumerable GetFormatters(ResolutionContext context) + { + Type valueType = context.SourceType; + IFormatterConfiguration typeSpecificFormatterConfig; + + if (context.PropertyMap != null) + { + foreach (IValueFormatter formatter in context.PropertyMap.GetFormatters()) + { + yield return formatter; + } + + if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig)) + { + if (!context.PropertyMap.FormattersToSkipContains(typeSpecificFormatterConfig.GetType())) + { + foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context)) + { + yield return typeSpecificFormatter; + } + } + } + } + else if (GetTypeSpecificFormatters().TryGetValue(valueType, out typeSpecificFormatterConfig)) + { + foreach (var typeSpecificFormatter in typeSpecificFormatterConfig.GetFormattersToApply(context)) + { + yield return typeSpecificFormatter; + } + } + + foreach (IValueFormatter formatter in GetFormatters()) + { + Type formatterType = GetFormatterType(formatter, context); + if (CheckPropertyMapSkipList(context, formatterType) && + CheckTypeSpecificSkipList(typeSpecificFormatterConfig, formatterType)) + { + yield return formatter; + } + } + } + + public void ConstructFormatterBy(Type formatterType, Func instantiator) + { + _formatters.RemoveAt(_formatters.Count - 1); + _formatters.Add(new DeferredInstantiatedFormatter(ctxt => instantiator())); + } + + public bool MapNullSourceValuesAsNull + { + get { return AllowNullDestinationValues; } + } + + public bool MapNullSourceCollectionsAsNull + { + get { return AllowNullCollections; } + } + + public void RecognizePrefixes(params string[] prefixes) + { + var orig = SourceMemberNameTransformer; + + SourceMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc); + } + + public void RecognizePostfixes(params string[] postfixes) + { + var orig = SourceMemberNameTransformer; + + SourceMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc); + } + + public void RecognizeAlias(string original, string alias) + { + var orig = SourceMemberNameTransformer; + + SourceMemberNameTransformer = val => AliasFunc(orig(val), original, alias); + } + + public void RecognizeDestinationPrefixes(params string[] prefixes) + { + var orig = DestinationMemberNameTransformer; + + DestinationMemberNameTransformer = val => prefixes.Aggregate(orig(val), PrefixFunc); + } + + public void RecognizeDestinationPostfixes(params string[] postfixes) + { + var orig = DestinationMemberNameTransformer; + + DestinationMemberNameTransformer = val => postfixes.Aggregate(orig(val), PostfixFunc); + } + + private static Type GetFormatterType(IValueFormatter formatter, ResolutionContext context) + { + return formatter is DeferredInstantiatedFormatter ? ((DeferredInstantiatedFormatter)formatter).GetFormatterType(context) : formatter.GetType(); + } + + private static bool CheckTypeSpecificSkipList(IFormatterConfiguration valueFormatter, Type formatterType) + { + if (valueFormatter == null) + { + return true; + } + + return !valueFormatter.GetFormatterTypesToSkip().Contains(formatterType); + } + + private static bool CheckPropertyMapSkipList(ResolutionContext context, Type formatterType) + { + if (context.PropertyMap == null) + return true; + + return !context.PropertyMap.FormattersToSkipContains(formatterType); + } + + private Func BuildCtor(Type type) + { + return context => + { + if (context.Options.ServiceCtor != null) + { + var obj = context.Options.ServiceCtor(type); + if (obj != null) + return (IValueFormatter)obj; + } + return (IValueFormatter)_formatterCtor(type); + }; + } + + } + + internal interface IFormatterCtorConfigurator + { + void ConstructFormatterBy(Type formatterType, Func instantiator); + } } \ No newline at end of file From 1a1c110b36fb891407b5b96d3c5c56d462e364df Mon Sep 17 00:00:00 2001 From: C-J Berg Date: Mon, 28 Nov 2011 00:47:49 +0100 Subject: [PATCH 2/2] Optimized FormatterExpression by replacing uncached Regex.Replace calls with basic string manipulations (Regex was unnecessary and expensive). --- .../Internal/FormatterExpression.cs | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/AutoMapper/Internal/FormatterExpression.cs b/src/AutoMapper/Internal/FormatterExpression.cs index cb7ef6ad26..eb088bedaa 100644 --- a/src/AutoMapper/Internal/FormatterExpression.cs +++ b/src/AutoMapper/Internal/FormatterExpression.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; namespace AutoMapper { @@ -11,16 +10,16 @@ internal class FormatterExpression : IFormatterExpression, IFormatterConfigurati private readonly IList _formatters = new List(); private readonly IDictionary _typeSpecificFormatters = new Dictionary(); private readonly IList _formattersToSkip = new List(); - private static readonly Func PrefixFunc = (src, prefix) => Regex.Replace(src, string.Format("(?:^{0})?(.*)", prefix), "$1"); - private static readonly Func PostfixFunc = (src, prefix) => Regex.Replace(src, string.Format("(.*)(?:{0})$", prefix), "$1"); - private static readonly Func AliasFunc = (src, original, alias) => Regex.Replace(src, string.Format("^({0})$", original), alias); + private static readonly Func PrefixFunc = (src, prefix) => DefaultPrefixTransformer(src, prefix); + private static readonly Func PostfixFunc = (src, postfix) => DefaultPostfixTransformer(src, postfix); + private static readonly Func AliasFunc = (src, original, alias) => DefaultAliasTransformer(src, original, alias); public FormatterExpression(Func formatterCtor) { _formatterCtor = formatterCtor; SourceMemberNamingConvention = new PascalCaseNamingConvention(); DestinationMemberNamingConvention = new PascalCaseNamingConvention(); - SourceMemberNameTransformer = s => Regex.Replace(s, "(?:^Get)?(.*)", "$1"); + SourceMemberNameTransformer = DefaultSourceMemberNameTransformer; DestinationMemberNameTransformer = s => s; AllowNullDestinationValues = true; } @@ -224,6 +223,40 @@ private Func BuildCtor(Type type) }; } + private static string DefaultPrefixTransformer(string src, string prefix) + { + return src != null + && !String.IsNullOrEmpty(prefix) + && src.StartsWith(prefix, StringComparison.Ordinal) + ? src.Substring(prefix.Length) + : src; + } + + private static string DefaultPostfixTransformer(string src, string postfix) + { + return src != null + && !String.IsNullOrEmpty(postfix) + && src.EndsWith(postfix, StringComparison.Ordinal) + ? src.Remove(src.Length - postfix.Length) + : src; + } + + private static string DefaultAliasTransformer(string src, string original, string @alias) + { + return src != null + && !String.IsNullOrEmpty(original) + && String.Equals(src, original, StringComparison.Ordinal) + ? @alias + : src; + } + + private static string DefaultSourceMemberNameTransformer(string src) + { + return src != null + && src.StartsWith("Get", StringComparison.Ordinal) + ? src.Substring(3) // Removes initial "Get" + : src; + } } internal interface IFormatterCtorConfigurator