Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- Fixed default for allowing null destination values (now false)

- Added postfix and prefix Configuration
- Added naming conventions
  • Loading branch information...
commit 78ad62eeac1d3335e1c716eba5a2f6a462006890 1 parent 64a61a7
@jbogard jbogard authored
View
BIN  lib/Rhino.Mocks.dll
Binary file not shown
View
BIN  release/AutoMapper-merged.zip
Binary file not shown
View
BIN  release/AutoMapper.dll
Binary file not shown
View
BIN  release/AutoMapper.zip
Binary file not shown
View
1  src/AutoMapper/AutoMapper.csproj
@@ -60,6 +60,7 @@
<Compile Include="AssemblyInfo.cs" />
<Compile Include="AutoMapperMappingException.cs" />
<Compile Include="IMappingEngineRunner.cs" />
+ <Compile Include="INamingConvention.cs" />
<Compile Include="Internal\DeferredInstantiatedConverter.cs" />
<Compile Include="Internal\DelegateFactory.cs" />
<Compile Include="Internal\ITypeMapFactory.cs" />
View
49 src/AutoMapper/Configuration.cs
@@ -32,6 +32,24 @@ public bool AllowNullDestinationValues
set { GetProfile(DefaultProfileName).AllowNullDestinationValues = value; }
}
+ public INamingConvention SourceMemberNamingConvention
+ {
+ get { return GetProfile(DefaultProfileName).SourceMemberNamingConvention; }
+ set { GetProfile(DefaultProfileName).SourceMemberNamingConvention = value; }
+ }
+
+ public INamingConvention DestinationMemberNamingConvention
+ {
+ get { return GetProfile(DefaultProfileName).DestinationMemberNamingConvention; }
+ set { GetProfile(DefaultProfileName).DestinationMemberNamingConvention = value; }
+ }
+
+ public Func<string, string> SourceMemberNameTransformer
+ {
+ get { return GetProfile(DefaultProfileName).SourceMemberNameTransformer; }
+ set { GetProfile(DefaultProfileName).SourceMemberNameTransformer = value; }
+ }
+
bool IProfileConfiguration.MapNullSourceValuesAsNull
{
get { return AllowNullDestinationValues; }
@@ -102,12 +120,28 @@ public IMappingExpression CreateMap(Type sourceType, Type destinationType)
return new MappingExpression(typeMap, _typeConverterCtor);
}
+ public void RecognizePrefixes(params string[] prefixes)
+ {
+ GetProfile(DefaultProfileName).RecognizePrefixes(prefixes);
+ }
+
+ public void RecognizePostfixes(params string[] postfixes)
+ {
+ GetProfile(DefaultProfileName).RecognizePostfixes(postfixes);
+ }
+
public TypeMap CreateTypeMap(Type source, Type destination)
{
- TypeMap typeMap = _typeMapFactory.CreateTypeMap(source, destination);
+ TypeMap typeMap = FindExplicitlyDefinedTypeMap(source, destination);
+
+ if (typeMap == null)
+ {
+ typeMap = _typeMapFactory.CreateTypeMap(source, destination, this);
+
+ _typeMaps.Add(typeMap);
+ _typeMapCache[new TypePair(source, destination)] = typeMap;
+ }
- _typeMaps.Add(typeMap);
- _typeMapCache[new TypePair(source, destination)] = typeMap;
return typeMap;
}
@@ -228,7 +262,7 @@ public IObjectMapper[] GetMappers()
private TypeMap FindTypeMap(object source, Type sourceType, Type destinationType)
{
- TypeMap typeMap = _typeMaps.FirstOrDefault(x => x.DestinationType == destinationType && x.SourceType == sourceType);
+ TypeMap typeMap = FindExplicitlyDefinedTypeMap(sourceType, destinationType);
if (typeMap == null)
{
@@ -256,7 +290,12 @@ private TypeMap FindTypeMap(object source, Type sourceType, Type destinationType
return typeMap;
}
- private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, ResolutionContext context)
+ private TypeMap FindExplicitlyDefinedTypeMap(Type sourceType, Type destinationType)
+ {
+ return _typeMaps.FirstOrDefault(x => x.DestinationType == destinationType && x.SourceType == sourceType);
+ }
+
+ private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, ResolutionContext context)
{
if (context.TypeMap != null)
{
View
4 src/AutoMapper/IFormatterExpression.cs
@@ -25,10 +25,12 @@ public interface IFormatterCtorExpression<TValueFormatter>
void ConstructedBy(Func<TValueFormatter> constructor);
}
- public interface IProfileExpression : IFormatterExpression
+ public interface IProfileExpression : IFormatterExpression, IMappingOptions
{
IMappingExpression<TSource, TDestination> CreateMap<TSource, TDestination>();
IMappingExpression CreateMap(Type sourceType, Type destinationType);
+ void RecognizePrefixes(params string[] prefixes);
+ void RecognizePostfixes(params string[] postfixes);
}
public interface IConfiguration : IProfileExpression
View
48 src/AutoMapper/INamingConvention.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace AutoMapper
+{
+ public interface INamingConvention
+ {
+ Regex SplittingExpression { get; }
+ string SeparatorCharacter { get; }
+ }
+
+ public interface IMappingOptions
+ {
+ INamingConvention SourceMemberNamingConvention { get; set; }
+ INamingConvention DestinationMemberNamingConvention { get; set; }
+ Func<string, string> SourceMemberNameTransformer { get; set; }
+ }
+
+ public class PascalCaseNamingConvention : INamingConvention
+ {
+ private readonly Regex _splittingExpression = new Regex(@"\p{Lu}[\p{Ll}0-9]*");
+
+ public Regex SplittingExpression
+ {
+ get { return _splittingExpression; }
+ }
+
+ public string SeparatorCharacter
+ {
+ get { return string.Empty; }
+ }
+ }
+
+ public class LowerUnderscoreNamingConvention : INamingConvention
+ {
+ private readonly Regex _splittingExpression = new Regex(@"[\p{Ll}0-9]+(?=_?)");
+
+ public Regex SplittingExpression
+ {
+ get { return _splittingExpression; }
+ }
+
+ public string SeparatorCharacter
+ {
+ get { return "_"; }
+ }
+ }
+}
View
30 src/AutoMapper/Internal/FormatterExpression.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.RegularExpressions;
namespace AutoMapper
{
@@ -10,16 +11,22 @@ internal class FormatterExpression : IFormatterExpression, IFormatterConfigurati
private readonly IList<IValueFormatter> _formatters = new List<IValueFormatter>();
private readonly IDictionary<Type, IFormatterConfiguration> _typeSpecificFormatters = new Dictionary<Type, IFormatterConfiguration>();
private readonly IList<Type> _formattersToSkip = new List<Type>();
+ private static readonly Func<string, string, string> PrefixFunc = (src, prefix) => Regex.Replace(src, string.Format("(?:^{0})?(.*)", prefix), "$1");
+ private static readonly Func<string, string, string> PostfixFunc = (src, prefix) => Regex.Replace(src, string.Format("(.*)(?:{0})$", prefix), "$1");
public FormatterExpression(Func<Type, IValueFormatter> formatterCtor)
{
_formatterCtor = formatterCtor;
+ SourceMemberNamingConvention = new PascalCaseNamingConvention();
+ DestinationMemberNamingConvention = new PascalCaseNamingConvention();
+ SourceMemberNameTransformer = s => Regex.Replace(s, "(?:^Get)?(.*)", "$1");
+ AllowNullDestinationValues = true;
}
- public bool AllowNullDestinationValues
- {
- get; set;
- }
+ public bool AllowNullDestinationValues { get; set; }
+ public INamingConvention SourceMemberNamingConvention { get; set; }
+ public INamingConvention DestinationMemberNamingConvention { get; set; }
+ public Func<string, string> SourceMemberNameTransformer { get; set; }
public IFormatterCtorExpression<TValueFormatter> AddFormatter<TValueFormatter>() where TValueFormatter : IValueFormatter
{
@@ -88,6 +95,21 @@ public bool MapNullSourceValuesAsNull
{
get { return AllowNullDestinationValues; }
}
+
+ 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);
+ }
+
}
internal interface IFormatterCtorConfigurator
View
2  src/AutoMapper/Internal/ITypeMapFactory.cs
@@ -4,6 +4,6 @@ namespace AutoMapper
{
public interface ITypeMapFactory
{
- TypeMap CreateTypeMap(Type sourceType, Type destinationType);
+ TypeMap CreateTypeMap(Type sourceType, Type destinationType, IMappingOptions mappingOptions);
}
}
View
42 src/AutoMapper/Internal/TypeMapFactory.cs
@@ -9,10 +9,10 @@ namespace AutoMapper
{
public class TypeMapFactory : ITypeMapFactory
{
- private static IDictionary<Type, TypeInfo> _typeInfos = new Dictionary<Type, TypeInfo>();
- private object _typeInfoSync = new object();
+ private static readonly IDictionary<Type, TypeInfo> _typeInfos = new Dictionary<Type, TypeInfo>();
+ private readonly object _typeInfoSync = new object();
- public TypeMap CreateTypeMap(Type sourceType, Type destinationType)
+ public TypeMap CreateTypeMap(Type sourceType, Type destinationType, IMappingOptions options)
{
var sourceTypeInfo = GetTypeInfo(sourceType);
var destTypeInfo = GetTypeInfo(destinationType);
@@ -23,7 +23,7 @@ public TypeMap CreateTypeMap(Type sourceType, Type destinationType)
{
var resolvers = new LinkedList<IValueResolver>();
- if (MapDestinationPropertyToSource(resolvers, sourceTypeInfo, destProperty.Name))
+ if (MapDestinationPropertyToSource(resolvers, sourceTypeInfo, destProperty.Name, options))
{
typeMap.AddPropertyMap(destProperty, resolvers);
}
@@ -50,27 +50,28 @@ private TypeInfo GetTypeInfo(Type type)
return typeInfo;
}
- private bool MapDestinationPropertyToSource(LinkedList<IValueResolver> resolvers, TypeInfo sourceType, string nameToSearch)
+ private bool MapDestinationPropertyToSource(LinkedList<IValueResolver> resolvers, TypeInfo sourceType, string nameToSearch, IMappingOptions mappingOptions)
{
var sourceProperties = sourceType.GetPublicReadAccessors();
var sourceNoArgMethods = sourceType.GetPublicNoArgMethods();
- IValueResolver resolver = FindTypeMember(sourceProperties, sourceNoArgMethods, nameToSearch);
+ IValueResolver resolver = FindTypeMember(sourceProperties, sourceNoArgMethods, nameToSearch, mappingOptions);
bool foundMatch = resolver != null;
if (!foundMatch)
{
- string[] matches = Regex.Matches(nameToSearch, @"\p{Lu}[\p{Ll}0-9]*")
+ string[] matches = mappingOptions.DestinationMemberNamingConvention.SplittingExpression
+ .Matches(nameToSearch)
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
for (int i = 0; i < matches.Length - 1; i++)
{
- NameSnippet snippet = CreateNameSnippet(matches, i);
+ NameSnippet snippet = CreateNameSnippet(matches, i, mappingOptions);
- IMemberAccessor valueResolver = FindTypeMember(sourceProperties, sourceNoArgMethods, snippet.First);
+ IMemberAccessor valueResolver = FindTypeMember(sourceProperties, sourceNoArgMethods, snippet.First, mappingOptions);
if (valueResolver == null)
{
@@ -79,7 +80,7 @@ private bool MapDestinationPropertyToSource(LinkedList<IValueResolver> resolvers
resolvers.AddLast(valueResolver);
- foundMatch = MapDestinationPropertyToSource(resolvers, GetTypeInfo(valueResolver.MemberType), snippet.Second);
+ foundMatch = MapDestinationPropertyToSource(resolvers, GetTypeInfo(valueResolver.MemberType), snippet.Second, mappingOptions);
if (foundMatch)
{
@@ -97,14 +98,23 @@ private bool MapDestinationPropertyToSource(LinkedList<IValueResolver> resolvers
return foundMatch;
}
- private static IMemberAccessor FindTypeMember(IEnumerable<IMemberAccessor> modelProperties, IEnumerable<MethodInfo> getMethods, string nameToSearch)
+ private static IMemberAccessor FindTypeMember(IEnumerable<IMemberAccessor> modelProperties, IEnumerable<MethodInfo> getMethods, string nameToSearch, IMappingOptions mappingOptions)
{
IMemberAccessor pi = modelProperties.FirstOrDefault(prop => NameMatches(prop.Name, nameToSearch));
if (pi != null)
return pi;
- string getName = "Get" + nameToSearch;
- MethodInfo mi = getMethods.FirstOrDefault(m => (NameMatches(m.Name, getName)) || NameMatches(m.Name, nameToSearch));
+ //string getName = "Get" + nameToSearch;
+ //MethodInfo mi = getMethods.FirstOrDefault(m => (NameMatches(m.Name, getName)) || NameMatches(m.Name, nameToSearch));
+ MethodInfo mi = getMethods.FirstOrDefault(m => NameMatches(m.Name, nameToSearch));
+ if (mi != null)
+ return new MethodAccessor(mi);
+
+ pi = modelProperties.FirstOrDefault(prop => NameMatches(mappingOptions.SourceMemberNameTransformer(prop.Name), nameToSearch));
+ if (pi != null)
+ return pi;
+
+ mi = getMethods.FirstOrDefault(m => NameMatches(mappingOptions.SourceMemberNameTransformer(m.Name), nameToSearch));
if (mi != null)
return new MethodAccessor(mi);
@@ -116,12 +126,12 @@ private static bool NameMatches(string memberName, string nameToMatch)
return String.Compare(memberName, nameToMatch, StringComparison.OrdinalIgnoreCase) == 0;
}
- private static NameSnippet CreateNameSnippet(IEnumerable<string> matches, int i)
+ private NameSnippet CreateNameSnippet(IEnumerable<string> matches, int i, IMappingOptions mappingOptions)
{
return new NameSnippet
{
- First = String.Concat(matches.Take(i + 1).ToArray()),
- Second = String.Concat(matches.Skip(i + 1).ToArray())
+ First = String.Join(mappingOptions.SourceMemberNamingConvention.SeparatorCharacter, matches.Take(i + 1).ToArray()),
+ Second = String.Join(mappingOptions.SourceMemberNamingConvention.SeparatorCharacter, matches.Skip(i + 1).ToArray())
};
}
View
7 src/AutoMapper/Mapper.cs
@@ -10,6 +10,12 @@ public static class Mapper
private static Configuration _configuration;
private static IMappingEngine _mappingEngine;
+ public static bool AllowNullDestinationValues
+ {
+ get { return Configuration.AllowNullDestinationValues; }
+ set { Configuration.AllowNullDestinationValues = value; }
+ }
+
public static TDestination Map<TSource, TDestination>(TSource source)
{
return Engine.Map<TSource, TDestination>(source);
@@ -184,5 +190,6 @@ private static IConfiguration Configuration
{
get { return (IConfiguration) ConfigurationProvider; }
}
+
}
}
View
43 src/AutoMapper/Profile.cs
@@ -21,22 +21,31 @@ protected virtual string ProfileName
get { return _profileName; }
}
- protected internal virtual void Configure()
+ public bool AllowNullDestinationValues
{
- // override in a derived class for custom configuration behavior
+ get { return GetProfile().AllowNullDestinationValues; }
+ set { GetProfile().AllowNullDestinationValues = value; }
}
- public void Initialize(Configuration configurator)
+ public INamingConvention SourceMemberNamingConvention
{
- _configurator = configurator;
+ get { return GetProfile().SourceMemberNamingConvention; }
+ set { GetProfile().SourceMemberNamingConvention = value; }
}
- public bool AllowNullDestinationValues
+ public INamingConvention DestinationMemberNamingConvention
{
- get { return GetProfile().AllowNullDestinationValues; }
- set { GetProfile().AllowNullDestinationValues = value; }
+ get { return GetProfile().DestinationMemberNamingConvention; }
+ set { GetProfile().DestinationMemberNamingConvention = value; }
}
+ public Func<string, string> SourceMemberNameTransformer
+ {
+ get { return GetProfile().SourceMemberNameTransformer; }
+ set { GetProfile().SourceMemberNameTransformer = value; }
+ }
+
+
public IFormatterCtorExpression<TValueFormatter> AddFormatter<TValueFormatter>() where TValueFormatter : IValueFormatter
{
return GetProfile().AddFormatter<TValueFormatter>();
@@ -81,6 +90,26 @@ public IMappingExpression CreateMap(Type sourceType, Type destinationType)
return map.WithProfile(ProfileName);
}
+ public void RecognizePrefixes(params string[] prefixes)
+ {
+ GetProfile().RecognizePrefixes(prefixes);
+ }
+
+ public void RecognizePostfixes(params string[] postfixes)
+ {
+ GetProfile().RecognizePostfixes(postfixes);
+ }
+
+ protected internal virtual void Configure()
+ {
+ // override in a derived class for custom configuration behavior
+ }
+
+ public void Initialize(Configuration configurator)
+ {
+ _configurator = configurator;
+ }
+
private FormatterExpression GetProfile()
{
return _configurator.GetProfile(ProfileName);
View
8 src/CommonAssemblyInfo.cs
@@ -5,7 +5,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4016
+// Runtime Version:2.0.50727.4013
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -13,11 +13,11 @@
//------------------------------------------------------------------------------
[assembly: ComVisibleAttribute(false)]
-[assembly: AssemblyVersionAttribute("0.3.1.105")]
-[assembly: AssemblyFileVersionAttribute("0.3.1.105")]
+[assembly: AssemblyVersionAttribute("0.3.1.106")]
+[assembly: AssemblyFileVersionAttribute("0.3.1.106")]
[assembly: AssemblyCopyrightAttribute("Copyright © Jimmy Bogard 2008-2009")]
[assembly: AssemblyProductAttribute("AutoMapper")]
[assembly: AssemblyCompanyAttribute("")]
[assembly: AssemblyConfigurationAttribute("Debug")]
-[assembly: AssemblyInformationalVersionAttribute("0.3.1.105")]
+[assembly: AssemblyInformationalVersionAttribute("0.3.1.106")]
View
1  src/UnitTests/Dictionaries.cs
@@ -174,6 +174,7 @@ public class FooDto
protected override void Establish_context()
{
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<Foo, FooDto>();
Mapper.CreateMap<FooDto, Foo>();
}
View
3  src/UnitTests/Enumerations.cs
@@ -203,6 +203,7 @@ public class When_mapping_from_a_null_object_with_an_enum
[SetUp]
public void SetUp()
{
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<SourceClass, DestinationClass>();
}
@@ -236,6 +237,7 @@ public class When_mapping_from_a_null_object_with_an_enum_on_a_nullable_enum
[SetUp]
public void SetUp()
{
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<SourceClass, DestinationClass>();
}
@@ -269,6 +271,7 @@ public class When_mapping_from_a_null_object_with_a_nullable_enum
[SetUp]
public void SetUp()
{
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<SourceClass, DestinationClass>();
}
View
1  src/UnitTests/General.cs
@@ -46,6 +46,7 @@ private class ModelObject
protected override void Establish_context()
{
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<ModelObject, ModelDto>();
_result = Mapper.Map<ModelObject, ModelDto>(null);
View
135 src/UnitTests/MemberResolution.cs
@@ -1115,6 +1115,141 @@ public void Should_allow_for_basic_mapping()
}
}
+ public class When_matching_source_and_destination_members_with_underscored_members : AutoMapperSpecBase
+ {
+ private Destination _destination;
+
+ private class Source
+ {
+ public SubSource some_source { get; set; }
+ }
+
+ private class SubSource
+ {
+ public int value { get; set; }
+ }
+
+ private class Destination
+ {
+ public int some_source_value { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ Mapper.Initialize(cfg =>
+ {
+ cfg.SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
+ cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
+ cfg.CreateMap<Source, Destination>();
+ });
+ }
+
+ protected override void Because_of()
+ {
+ _destination = Mapper.Map<Source, Destination>(new Source {some_source = new SubSource {value = 8}});
+ }
+
+ [Test]
+ public void Should_use_underscores_as_tokenizers_to_flatten()
+ {
+ _destination.some_source_value.ShouldEqual(8);
+ }
+ }
+
+ public class When_source_members_contain_prefixes : AutoMapperSpecBase
+ {
+ private Destination _destination;
+
+ private class Source
+ {
+ public int FooValue { get; set; }
+ public int GetOtherValue()
+ {
+ return 10;
+ }
+ }
+
+ public class Destination
+ {
+ public int Value { get; set; }
+ public int OtherValue { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ Mapper.Initialize(cfg =>
+ {
+ cfg.RecognizePrefixes("Foo");
+ cfg.CreateMap<Source, Destination>();
+ });
+ }
+
+ protected override void Because_of()
+ {
+ _destination = Mapper.Map<Source, Destination>(new Source {FooValue = 5});
+ }
+
+ [Test]
+ public void Registered_prefixes_ignored()
+ {
+ _destination.Value.ShouldEqual(5);
+ }
+
+ [Test]
+ public void Default_prefix_included()
+ {
+ _destination.OtherValue.ShouldEqual(10);
+ }
+ }
+
+
+ public class When_source_members_contain_postfixes_and_prefixes : AutoMapperSpecBase
+ {
+ private Destination _destination;
+
+ private class Source
+ {
+ public int FooValueBar { get; set; }
+ public int GetOtherValue()
+ {
+ return 10;
+ }
+ }
+
+ public class Destination
+ {
+ public int Value { get; set; }
+ public int OtherValue { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ Mapper.Initialize(cfg =>
+ {
+ cfg.RecognizePrefixes("Foo");
+ cfg.RecognizePostfixes("Bar");
+ cfg.CreateMap<Source, Destination>();
+ });
+ }
+
+ protected override void Because_of()
+ {
+ _destination = Mapper.Map<Source, Destination>(new Source { FooValueBar = 5 });
+ }
+
+ [Test]
+ public void Registered_prefixes_ignored()
+ {
+ _destination.Value.ShouldEqual(5);
+ }
+
+ [Test]
+ public void Default_prefix_included()
+ {
+ _destination.OtherValue.ShouldEqual(10);
+ }
+ }
+
}
public static class MapFromExtensions
View
7 src/UnitTests/NullBehavior.cs
@@ -42,6 +42,7 @@ protected override void Establish_context()
var model = new ModelObject();
model.Sub = null;
+ Mapper.AllowNullDestinationValues = false;
Mapper.CreateMap<ModelObject, ModelDto>();
Mapper.CreateMap<ModelSubObject, ModelSubDto>();
@@ -166,7 +167,7 @@ protected override void Establish_context()
{
Mapper.CreateProfile("MapsNulls", p =>
{
- p.AllowNullDestinationValues = true;
+ p.AllowNullDestinationValues = false;
p.CreateMap<NullSource, NullDestination>();
});
Mapper.CreateMap<DefaultSource, DefaultDestination>();
@@ -181,13 +182,13 @@ protected override void Because_of()
[Test]
public void Should_use_default_behavior_in_default_profile()
{
- _defaultResult.Value.ShouldNotBeNull();
+ _defaultResult.Value.ShouldBeNull();
}
[Test]
public void Should_use_overridden_null_behavior_in_profile()
{
- _nullResult.Value.ShouldBeNull();
+ _nullResult.Value.ShouldNotBeNull();
}
}
View
3  src/UnitTests/SelfConfiguration.cs
@@ -53,6 +53,9 @@ protected override void DescribeConfiguration(IMappingExpression<Source, Destina
{
map.ForMember(x => x.ConfiguredProperty, o => o.MapFrom(x => x.Property));
map.ForMember(x => x.AllowNullDestinationValues, o => o.Ignore());
+ map.ForMember(x => x.DestinationMemberNamingConvention, o => o.Ignore());
+ map.ForMember(x => x.SourceMemberNamingConvention, o => o.Ignore());
+ map.ForMember(x => x.SourceMemberNameTransformer, o => o.Ignore());
}
}
}
View
40 src/UnitTests/Tests/ConfigurationSpecs.cs
@@ -0,0 +1,40 @@
+using AutoMapper.Mappers;
+using NBehave.Spec.NUnit;
+using NUnit.Framework;
+
+namespace AutoMapper.UnitTests.Tests
+{
+ namespace ConfigurationSpecs
+ {
+ public class When_configuring_a_type_pair_twice : SpecBase
+ {
+ private TypeMap _expected;
+ private Configuration _configuration;
+
+ private class Source { }
+ private class Destination { }
+
+ protected override void Establish_context()
+ {
+ _configuration = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
+ _configuration.CreateMap<Source, Destination>();
+
+ _expected = _configuration.FindTypeMapFor(null, typeof(Source), typeof(Destination));
+ }
+
+ protected override void Because_of()
+ {
+ _configuration.CreateMap<Source, Destination>();
+ }
+
+ [Test]
+ public void Should_not_redefine_the_map()
+ {
+ TypeMap actual = _configuration.FindTypeMapFor(null, typeof (Source), typeof (Destination));
+
+ actual.ShouldBeTheSameAs(_expected);
+ }
+ }
+
+ }
+}
View
173 src/UnitTests/Tests/TypeMapFactorySpecs.cs
@@ -1,25 +1,17 @@
+using System;
+using System.Text.RegularExpressions;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using System.Linq;
+using Rhino.Mocks;
namespace AutoMapper.UnitTests.Tests
{
- public class TypeMapFactory_Context : SpecBase
+ public class When_constructing_type_maps_with_matching_property_names : SpecBase
{
- protected override void Establish_context()
- {
- Factory = new TypeMapFactory();
- }
+ private TypeMapFactory _factory;
- protected TypeMapFactory Factory
- {
- get; set;
- }
- }
-
- public class When_constructing_type_maps_with_matching_property_names : TypeMapFactory_Context
- {
- public class Source
+ public class Source
{
public int Value { get; set; }
public int SomeOtherValue { get; set; }
@@ -30,11 +22,20 @@ public class Destination
public int Value { get; set; }
public int SomeOtherValue { get; set; }
}
+
+ protected override void Establish_context()
+ {
+ _factory = new TypeMapFactory();
+ }
- [Test]
+ [Test]
public void Should_map_properties_with_same_name()
{
- var typeMap = Factory.CreateTypeMap(typeof (Source), typeof (Destination));
+ var mappingOptions = CreateStub<IMappingOptions>();
+ mappingOptions.SourceMemberNamingConvention = new PascalCaseNamingConvention();
+ mappingOptions.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
+
+ var typeMap = _factory.CreateTypeMap(typeof(Source), typeof(Destination), mappingOptions);
var propertyMaps = typeMap.GetPropertyMaps();
@@ -42,4 +43,144 @@ public void Should_map_properties_with_same_name()
}
}
+ public class When_using_a_custom_source_naming_convention : SpecBase
+ {
+ private TypeMapFactory _factory;
+ private TypeMap _map;
+ private IMappingOptions _mappingOptions;
+
+ private class Source
+ {
+ public SubSource some__source { get; set; }
+ }
+
+ private class SubSource
+ {
+ public int value { get; set; }
+ }
+
+ private class Destination
+ {
+ public int SomeSourceValue { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ INamingConvention namingConvention = CreateStub<INamingConvention>();
+ namingConvention.Stub(nc => nc.SeparatorCharacter).Return("__");
+
+ _mappingOptions = CreateStub<IMappingOptions>();
+ _mappingOptions.SourceMemberNamingConvention = namingConvention;
+ _mappingOptions.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
+ _mappingOptions.SourceMemberNameTransformer = s => s;
+
+ _factory = new TypeMapFactory();
+
+ }
+
+ protected override void Because_of()
+ {
+ _map = _factory.CreateTypeMap(typeof(Source), typeof(Destination), _mappingOptions);
+ }
+
+ [Test]
+ public void Should_split_using_naming_convention_rules()
+ {
+ _map.GetPropertyMaps().Count().ShouldEqual(1);
+ }
+ }
+
+ public class When_using_a_custom_destination_naming_convention : SpecBase
+ {
+ private TypeMapFactory _factory;
+ private TypeMap _map;
+ private IMappingOptions _mappingOptions;
+
+ private class Source
+ {
+ public SubSource SomeSource { get; set; }
+ }
+
+ private class SubSource
+ {
+ public int Value { get; set; }
+ }
+
+ private class Destination
+ {
+ public int some__source__value { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ INamingConvention namingConvention = CreateStub<INamingConvention>();
+
+ namingConvention.Stub(nc => nc.SplittingExpression).Return(new Regex(@"[\p{Ll}0-9]*(?=_?)"));
+
+ _mappingOptions = CreateStub<IMappingOptions>();
+ _mappingOptions.SourceMemberNamingConvention = new PascalCaseNamingConvention();
+ _mappingOptions.DestinationMemberNamingConvention = namingConvention;
+ _mappingOptions.SourceMemberNameTransformer = s => s;
+
+ _factory = new TypeMapFactory();
+ }
+
+ protected override void Because_of()
+ {
+ _map = _factory.CreateTypeMap(typeof(Source), typeof(Destination), _mappingOptions);
+ }
+
+ [Test]
+ public void Should_split_using_naming_convention_rules()
+ {
+ _map.GetPropertyMaps().Count().ShouldEqual(1);
+ }
+ }
+
+ public class When_specifying_a_custom_transformation_method : SpecBase
+ {
+ private IMappingOptions _mappingOptions;
+ private TypeMapFactory _factory;
+ private TypeMap _map;
+
+ private class Source
+ {
+ public int FooValueBar { get; set; }
+ public int FooValueBar2 { get; set; }
+ }
+
+ private class Destination
+ {
+ public int Value { get; set; }
+ public int FooValueBar2 { get; set; }
+ }
+
+ protected override void Establish_context()
+ {
+ _mappingOptions = CreateStub<IMappingOptions>();
+ Func<string, string> transformer = s =>
+ {
+ s = Regex.Replace(s, "(?:^Foo)?(.*)", "$1");
+ return Regex.Replace(s, "(.*)(?:Bar|Blah)$", "$1");
+ };
+ _mappingOptions.SourceMemberNameTransformer = transformer;
+ _mappingOptions.SourceMemberNamingConvention = new PascalCaseNamingConvention();
+ _mappingOptions.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
+
+ _factory = new TypeMapFactory();
+ }
+
+ protected override void Because_of()
+ {
+ _map = _factory.CreateTypeMap(typeof(Source), typeof(Destination), _mappingOptions);
+ }
+
+ [Test]
+ public void Should_execute_transform_when_members_do_not_match()
+ {
+ _map.GetPropertyMaps().Count().ShouldEqual(2);
+ }
+ }
+
+
}
View
5 src/UnitTests/UnitTests.csproj
@@ -54,6 +54,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\NUnit.framework.dll</HintPath>
</Reference>
+ <Reference Include="Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\Rhino.Mocks.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -93,6 +97,7 @@
<Compile Include="TesterExtensions.cs" />
<Compile Include="ConfigurationValidation.cs" />
<Compile Include="ResolutionContextTester.cs" />
+ <Compile Include="Tests\ConfigurationSpecs.cs" />
<Compile Include="Tests\MapperTests.cs" />
<Compile Include="Tests\TypeInfoSpecs.cs" />
<Compile Include="Tests\TypeMapFactorySpecs.cs" />
Please sign in to comment.
Something went wrong with that request. Please try again.