Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,8 @@ jobs:
- name: Add AutoMapper Myget Source
run: dotnet nuget add source https://www.myget.org/F/automapperdev/api/v3/index.json -n automappermyget

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore

- name: Test
run: dotnet test --no-restore --verbosity normal
run: dotnet test --configuration Release --verbosity normal

- name: Pack and push
env:
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,8 @@ jobs:
with:
fetch-depth: 0

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore

- name: Test
run: dotnet test --no-restore --verbosity normal
run: dotnet test --configuration Release --verbosity normal

- name: Pack and push
env:
Expand Down
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
<PropertyGroup>
<Summary>Expression mapping (OData) extensions for AutoMapper</Summary>
<Description>Expression mapping (OData) extensions for AutoMapper</Description>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyOriginatorKeyFile>..\..\AutoMapper.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageId>AutoMapper.Extensions.ExpressionMapping</PackageId>
<PackageIconUrl>https://s3.amazonaws.com/automapper/icon.png</PackageIconUrl>
<PackageProjectUrl>http://automapper.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping/blob/master/LICENSE</PackageLicenseUrl>
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://automapper.org</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/Amtote/AutoMapper.Extensions.ExpressionMapping</RepositoryUrl>
<MinVerDefaultPreReleasePhase>amtote</MinVerDefaultPreReleasePhase>
Expand All @@ -24,13 +24,32 @@
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath="" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="[11.0.0,12.0.0)" />
<PackageReference Include="AutoMapper" Version="[13.0.0,14.0.0)" />
<PackageReference Include="MinVer" Version="2.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected override Expression VisitBinary(BinaryExpression node)
var newLeft = Visit(node.Left);
var newRight = Visit(node.Right);

// check if the non-string expression is a null constent
// check if the non-string expression is a null constant
// as this would lead to a "null.ToString()" and thus an error when executing the expression
if (newLeft.Type != newRight.Type && newRight.Type == typeof(string) && !IsNullConstant(newLeft))
newLeft = Call(newLeft, typeof(object).GetDeclaredMethod("ToString"));
Expand Down Expand Up @@ -206,7 +206,7 @@ protected override Expression VisitMember(MemberExpression node)
if (constantVisitor.IsConstant)
return node;

SetSorceSubTypes(propertyMap);
SetSourceSubTypes(propertyMap);

var replacedExpression = Visit(node.Expression);
if (replacedExpression == node.Expression)
Expand Down Expand Up @@ -282,7 +282,7 @@ private PropertyMap GetExistingPropertyMapFor(MemberInfo destinationProperty, Ty
return typeMap.PropertyMaps.FirstOrDefault(pm => pm.DestinationName == destinationProperty.Name);
}

private void SetSorceSubTypes(PropertyMap propertyMap)
private void SetSourceSubTypes(PropertyMap propertyMap)
{
if (propertyMap.SourceMember is PropertyInfo info)
_destSubTypes = info.PropertyType.GetTypeInfo().GenericTypeArguments.Concat(new[] { info.PropertyType }).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using AutoMapper.Extensions.ExpressionMapping.Structures;
using AutoMapper.Internal;

namespace AutoMapper.Extensions.ExpressionMapping.Extensions
{
Expand Down Expand Up @@ -202,5 +203,13 @@ public static List<Type> GetUnderlyingGenericTypes(this Type type) =>
type == null || !type.GetTypeInfo().IsGenericType
? new List<Type>()
: type.GetGenericArguments().ToList();

public static bool IsEnumType(this Type type)
{
if (type.IsNullableType())
type = Nullable.GetUnderlyingType(type);

return type.IsEnum();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public MemberExpression Result
if (string.IsNullOrEmpty(result) || next.Contains(result))
result = next;
else throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
Resource.includeExpressionTooComplex,
Properties.Resources.includeExpressionTooComplex,
string.Concat(_newParentExpression.Type.Name, period, result),
string.Concat(_newParentExpression.Type.Name, period, next)));

Expand All @@ -50,7 +50,7 @@ protected override Expression VisitMember(MemberExpression node)
if (node.Expression.NodeType == ExpressionType.MemberAccess && node.Type.IsLiteralType())
_memberExpressions.Add((MemberExpression)node.Expression);
else if (node.Expression.NodeType == ExpressionType.Parameter && node.Type.IsLiteralType())
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.mappedMemberIsChildOfTheParameterFormat, node.GetPropertyFullName(), node.Type.FullName, sType.FullName));
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.mappedMemberIsChildOfTheParameterFormat, node.GetPropertyFullName(), node.Type.FullName, sType.FullName));
else
_memberExpressions.Add(node);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using AutoMapper.Internal;
using AutoMapper.Extensions.ExpressionMapping.Extensions;
using AutoMapper.Extensions.ExpressionMapping.Structures;

Expand All @@ -18,6 +16,9 @@ public MapIncludesVisitor(IMapper mapper, IConfigurationProvider configurationPr

protected override Expression VisitLambda<T>(Expression<T> node)
{
if (!node.Body.Type.IsLiteralType())
return base.VisitLambda(node);

var ex = this.Visit(node.Body);

var mapped = Expression.Lambda(ex, node.GetDestinationParameterExpressions(this.InfoDictionary, this.TypeMappings));
Expand All @@ -27,6 +28,9 @@ protected override Expression VisitLambda<T>(Expression<T> node)

protected override Expression VisitMember(MemberExpression node)
{
if (!node.Type.IsLiteralType())
return base.VisitMember(node);

var parameterExpression = node.GetParameterExpression();
if (parameterExpression == null)
return base.VisitMember(node);
Expand Down
37 changes: 27 additions & 10 deletions src/AutoMapper.Extensions.ExpressionMapping/MapperExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ TDestDelegate MapBody(Dictionary<Type, Type> typeMappings, XpressionMapperVisito
TDestDelegate GetLambda(Dictionary<Type, Type> typeMappings, XpressionMapperVisitor visitor, Expression mappedBody)
{
if (mappedBody == null)
throw new InvalidOperationException(Resource.cantRemapExpression);
throw new InvalidOperationException(Properties.Resources.cantRemapExpression);

return (TDestDelegate)Lambda
(
Expand Down Expand Up @@ -255,7 +255,7 @@ public static List<ParameterExpression> GetDestinationParameterExpressions(this
/// <returns></returns>
public static Dictionary<Type, Type> AddTypeMapping<TSource, TDest>(this Dictionary<Type, Type> typeMappings, IConfigurationProvider configurationProvider)
=> typeMappings == null
? throw new ArgumentException(Resource.typeMappingsDictionaryIsNull)
? throw new ArgumentException(Properties.Resources.typeMappingsDictionaryIsNull)
: typeMappings.AddTypeMapping(configurationProvider, typeof(TSource), typeof(TDest));

private static bool HasUnderlyingType(this Type type)
Expand Down Expand Up @@ -284,7 +284,7 @@ private static void AddUnderlyingTypes(this Dictionary<Type, Type> typeMappings,
public static Dictionary<Type, Type> AddTypeMapping(this Dictionary<Type, Type> typeMappings, IConfigurationProvider configurationProvider, Type sourceType, Type destType)
{
if (typeMappings == null)
throw new ArgumentException(Resource.typeMappingsDictionaryIsNull);
throw new ArgumentException(Properties.Resources.typeMappingsDictionaryIsNull);

if (sourceType.GetTypeInfo().IsGenericType && sourceType.GetGenericTypeDefinition() == typeof(Expression<>))
{
Expand Down Expand Up @@ -335,29 +335,46 @@ void AddTypeMaps(TypeMap typeMap)
/// <returns></returns>
public static Type ReplaceType(this Dictionary<Type, Type> typeMappings, Type sourceType)
{
if (!sourceType.IsGenericType)
if (sourceType.IsArray)
{
return typeMappings.TryGetValue(sourceType, out Type destType) ? destType : sourceType;
if (typeMappings.TryGetValue(sourceType, out Type destType))
return destType;

if (typeMappings.TryGetValue(sourceType.GetElementType(), out Type destElementType))
{
int rank = sourceType.GetArrayRank();
return rank == 1
? destElementType.MakeArrayType()
: destElementType.MakeArrayType(rank);
}

return sourceType;
}
else
else if (sourceType.IsGenericType)
{
if (typeMappings.TryGetValue(sourceType, out Type destType))
return destType;
else
{
return sourceType.GetGenericTypeDefinition().MakeGenericType
(
sourceType
.GetGenericArguments()
.Select(type => typeMappings.ReplaceType(type))
.Select(typeMappings.ReplaceType)
.ToArray()
);
}
}
else
{
return typeMappings.TryGetValue(sourceType, out Type destType) ? destType : sourceType;
}
}

private static Dictionary<Type, Type> AddTypeMappingsFromDelegates(this Dictionary<Type, Type> typeMappings, IConfigurationProvider configurationProvider, Type sourceType, Type destType)
{
if (typeMappings == null)
throw new ArgumentException(Resource.typeMappingsDictionaryIsNull);
throw new ArgumentException(Properties.Resources.typeMappingsDictionaryIsNull);

typeMappings.DoAddTypeMappingsFromDelegates
(
Expand All @@ -372,7 +389,7 @@ private static Dictionary<Type, Type> AddTypeMappingsFromDelegates(this Dictiona
private static void DoAddTypeMappingsFromDelegates(this Dictionary<Type, Type> typeMappings, IConfigurationProvider configurationProvider, List<Type> sourceArguments, List<Type> destArguments)
{
if (sourceArguments.Count != destArguments.Count)
throw new ArgumentException(Resource.invalidArgumentCount);
throw new ArgumentException(Properties.Resources.invalidArgumentCount);

for (int i = 0; i < sourceArguments.Count; i++)
{
Expand All @@ -396,7 +413,7 @@ private static void DoAddTypeMappings(this Dictionary<Type, Type> typeMappings,
private static Type GetSourceMemberType(this PropertyMap propertyMap)
=> propertyMap.CustomMapExpression != null
? propertyMap.CustomMapExpression.ReturnType
: propertyMap.SourceMember.GetMemberType();
: propertyMap.SourceMembers.Last().GetMemberType();

private static void FindChildPropertyTypeMaps(this Dictionary<Type, Type> typeMappings, IConfigurationProvider ConfigurationProvider, Type source, Type dest)
{
Expand Down
Loading