Skip to content

Commit

Permalink
Added NameValueCollectionMapper so that NameValueCollections can be m…
Browse files Browse the repository at this point in the history
…apped. Fixes existing issue where the mappin attempt falls back to an IList, resulting in an InvalidCastException

fixes AutoMapper#141
  • Loading branch information
csano authored and jbogard committed Dec 11, 2011
1 parent 705fc60 commit f3e1ed6
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 7 deletions.
15 changes: 8 additions & 7 deletions src/AutoMapper/AutoMapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="MemberList.cs" />
<Compile Include="Mappers\NameValueCollectionMapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AutoMapperMappingException.cs" />
<Compile Include="Configuration\MapperConfiguration.cs" />
Expand Down Expand Up @@ -200,11 +201,11 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
3 changes: 3 additions & 0 deletions src/AutoMapper/Mappers/MapperRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public static class MapperRegistry
new EnumMapper(),
new ArrayMapper(),
new EnumerableToDictionaryMapper(),
#if !SILVERLIGHT
new NameValueCollectionMapper(),
#endif
new DictionaryMapper(),
#if !SILVERLIGHT
new ListSourceMapper(),
Expand Down
27 changes: 27 additions & 0 deletions src/AutoMapper/Mappers/NameValueCollectionMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Specialized;

namespace AutoMapper.Mappers
{
public class NameValueCollectionMapper : IObjectMapper
{
public object Map(ResolutionContext context, IMappingEngineRunner mapper)
{
if (!IsMatch(context) || context.SourceValue == null)
return null;

var nvc = new NameValueCollection();
var source = context.SourceValue as NameValueCollection;
foreach (var s in source.AllKeys)
nvc.Add(s, source[s]);

return nvc;
}

public bool IsMatch(ResolutionContext context)
{
return
context.SourceType == typeof(NameValueCollection) &&
context.DestinationType == typeof (NameValueCollection);
}
}
}
14 changes: 14 additions & 0 deletions src/UnitTests/CollectionMapping.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using NUnit.Framework;
using Should;
#if !SILVERLIGHT
Expand Down Expand Up @@ -272,6 +273,19 @@ public void Should_replace_destination_list()
Assert.That(master.Details, Is.Not.SameAs(originalCollection));
}

#if !SILVERLIGHT
[Test]
public void Should_map_to_NameValueCollection() {
// initially results in the following exception:
// ----> System.InvalidCastException : Unable to cast object of type 'System.Collections.Specialized.NameValueCollection' to type 'System.Collections.IList'.
// this was fixed by adding NameValueCollectionMapper to the MapperRegistry.
var c = new NameValueCollection();
var mappedCollection = Mapper.Map<NameValueCollection, NameValueCollection>(c);

Assert.IsNotNull(mappedCollection);
}
#endif

#if SILVERLIGHT
public class HashSet<T> : Collection<T>
{
Expand Down
103 changes: 103 additions & 0 deletions src/UnitTests/Mappers/NameValueCollectionMapperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System;
using System.Collections.Specialized;
using AutoMapper;
using AutoMapper.Mappers;
using NUnit.Framework;

namespace Automapper.UnitTests.Mappers
{
[TestFixture]
public class NameValueCollectionMapperTests
{
[TestFixture]
public class IsMatch
{
[Test]
public void ReturnsTrueWhenBothSourceAndDestinationTypesAreNameValueCollection()
{
var rc = new ResolutionContext(null, null, null, typeof(NameValueCollection), typeof(NameValueCollection), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.IsMatch(rc);

Assert.IsTrue(result);
}

[Test]
public void ReturnsIsFalseWhenDestinationTypeIsNotNameValueCollection()
{
var rc = new ResolutionContext(null, null, null, typeof(NameValueCollection), typeof(Object), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.IsMatch(rc);

Assert.IsFalse(result);
}

[Test]
public void ReturnsIsFalseWhenSourceTypeIsNotNameValueCollection()
{
var rc = new ResolutionContext(null, null, null, typeof(Object), typeof(NameValueCollection), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.IsMatch(rc);

Assert.IsFalse(result);
}
}

[TestFixture]
public class Map
{
[Test]
public void ReturnsNullIfSourceTypeIsNotNameValueCollection()
{
var rc = new ResolutionContext(null, new Object(), new NameValueCollection(), typeof(Object), typeof(NameValueCollection), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.Map(rc, null);

Assert.IsNull(result);
}

[Test]
public void ReturnsNullIfSourceValueIsNull()
{
var rc = new ResolutionContext(null, null, new NameValueCollection(), typeof(NameValueCollection), typeof(NameValueCollection), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.Map(rc, null);

Assert.IsNull(result);
}

[Test]
public void ReturnsEmptyCollectionWhenSourceCollectionIsEmpty()
{
var sourceValue = new NameValueCollection();
var rc = new ResolutionContext(null, sourceValue, new NameValueCollection(), typeof(NameValueCollection), typeof(NameValueCollection), null);
var nvcm = new NameValueCollectionMapper();

var result = nvcm.Map(rc, null) as NameValueCollection;

Assert.IsEmpty(result);
}

[Test]
public void ReturnsMappedObjectWithExpectedValuesWhenSourceCollectionHasOneItem()
{
var sourceValue = new NameValueCollection() { { "foo", "bar" } };
var rc = new ResolutionContext(null, sourceValue, new NameValueCollection(), typeof(NameValueCollection), typeof(NameValueCollection), null);

var nvcm = new NameValueCollectionMapper();

var result = nvcm.Map(rc, null) as NameValueCollection;

Assert.AreEqual(1, result.Count);
Assert.AreEqual("foo", result.AllKeys[0]);
Assert.AreEqual("bar", result["foo"]);
}
}

}
}
1 change: 1 addition & 0 deletions src/UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
<Compile Include="Internal\PrimitiveExtensionsTester.cs" />
<Compile Include="Internationalization.cs" />
<Compile Include="Bug\LazyCollectionMapping.cs" />
<Compile Include="Mappers\NameValueCollectionMapperTests.cs" />
<Compile Include="Mappers\TypeHelperTests.cs">
<SubType>Code</SubType>
</Compile>
Expand Down

0 comments on commit f3e1ed6

Please sign in to comment.