Skip to content

Commit

Permalink
feat: use IEnumerable Dictionary constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyMakkison committed Sep 16, 2023
1 parent b54b9a5 commit a9c7a6c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ or CollectionType.IDictionary
or CollectionType.IReadOnlyDictionary
)
{
if (TryGetFromEnumerable(ctx, keyMapping, valueMapping) is { } toDictionary)
return toDictionary;

var targetDictionarySymbol = ctx.Types.Get(typeof(Dictionary<,>)).Construct(keyMapping.TargetType, valueMapping.TargetType);
ctx.ObjectFactories.TryFindObjectFactory(ctx.Source, ctx.Target, out var dictionaryObjectFactory);
return new ForEachSetDictionaryMapping(
Expand Down Expand Up @@ -135,6 +138,34 @@ private static (INewInstanceMapping, INewInstanceMapping)? BuildKeyValueMapping(
return (keyMapping, valueMapping);
}

private static INewInstanceMapping? TryGetFromEnumerable(
MappingBuilderContext ctx,
INewInstanceMapping keyMapping,
INewInstanceMapping valueMapping
)
{
if (!keyMapping.IsSynthetic || !valueMapping.IsSynthetic || keyMapping.TargetType.IsNullable())
return null;

// use .NET 8 method .ToDictionary() if value and key mapping is synthetic
var enumerableType = ctx.Types.Get(typeof(IEnumerable<>));
var dictionaryType = ctx.Types.Get(typeof(Dictionary<,>));

var fromEnumerableCtor = dictionaryType.Constructors.FirstOrDefault(
x =>
x is { Parameters.Length: 1 }
&& SymbolEqualityComparer.Default.Equals(((INamedTypeSymbol)x.Parameters[0].Type).ConstructedFrom, enumerableType)
);

if (fromEnumerableCtor != null)
{
var constructedDictionary = dictionaryType.Construct(keyMapping.TargetType, valueMapping.TargetType);
return new CtorMapping(ctx.Source, constructedDictionary);
}

return null;
}

private static INamedTypeSymbol? GetExplicitIndexer(MappingBuilderContext ctx)
{
if (
Expand Down
44 changes: 4 additions & 40 deletions test/Riok.Mapperly.Tests/Mapping/DictionaryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,7 @@ public void DictionaryToSameDictionaryDeepCloning()
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::System.Collections.Generic.Dictionary<string, long>(source.Count);
foreach (var item in source)
{
target[item.Key] = item.Value;
}
return target;
"""
);
.HaveSingleMethodBody("return new global::System.Collections.Generic.Dictionary<string, long>(source);");
}

[Fact]
Expand Down Expand Up @@ -126,16 +117,7 @@ public void KeyValueEnumerableToIDictionary()
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::System.Collections.Generic.Dictionary<string, int>();
foreach (var item in source)
{
target[item.Key] = item.Value;
}
return target;
"""
);
.HaveSingleMethodBody("return new global::System.Collections.Generic.Dictionary<string, int>(source);");
}

[Fact]
Expand All @@ -145,16 +127,7 @@ public void CustomDictionaryToIDictionary()
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::System.Collections.Generic.Dictionary<string, int>(source.Count);
foreach (var item in source)
{
target[item.Key] = item.Value;
}
return target;
"""
);
.HaveSingleMethodBody("return new global::System.Collections.Generic.Dictionary<string, int>(source);");
}

[Fact]
Expand All @@ -164,16 +137,7 @@ public void CustomKeyValueListToIDictionary()
TestHelper
.GenerateMapper(source)
.Should()
.HaveSingleMethodBody(
"""
var target = new global::System.Collections.Generic.Dictionary<string, int>(source.Count);
foreach (var item in source)
{
target[item.Key] = item.Value;
}
return target;
"""
);
.HaveSingleMethodBody("return new global::System.Collections.Generic.Dictionary<string, int>(source);");
}

[Fact]
Expand Down

0 comments on commit a9c7a6c

Please sign in to comment.