Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: ./Push.ps1
shell: pwsh
- name: Artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: artifacts
path: artifacts/**/*
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
run: ./Push.ps1
shell: pwsh
- name: Artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: artifacts
path: artifacts/**/*
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ If you're still running into problems, file an issue above.
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).

AutoMapper is Copyright © 2009 [Jimmy Bogard](https://jimmybogard.com) and other contributors under the [MIT license](LICENSE.txt).
AutoMapper is Copyright © 2009 [Jimmy Bogard](https://jimmybogard.com) and other contributors under the [MIT license](https://github.com/AutoMapper/AutoMapper?tab=MIT-1-ov-file#MIT-1-ov-file).

### .NET Foundation

Expand Down
19 changes: 18 additions & 1 deletion src/AutoMapper/ApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,25 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMappe
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.UseExistingValueAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.ValueConverterAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'AutoMapper.Configuration.Annotations.ValueResolverAttribute' changed from '[AttributeUsageAttribute(384)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Field | AttributeTargets.Property)]' in the implementation.
CannotSealType : Type 'AutoMapper.Internal.Mappers.AssignableMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.CollectionMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ConstructorMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ConversionOperatorMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ConvertMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.EnumToEnumMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.FromDynamicMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.FromStringDictionaryMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.KeyValueMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.MultidimensionalArrayFiller' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
TypeCannotChangeClassification : Type 'AutoMapper.Internal.Mappers.MultidimensionalArrayFiller' is a 'struct' in the implementation but is a 'class' in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.NullableDestinationMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.NullableSourceMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ParseStringMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.StringToEnumMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ToDynamicMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ToStringDictionaryMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.ToStringMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotSealType : Type 'AutoMapper.Internal.Mappers.UnderlyingTypeEnumMapper' is actually (has the sealed modifier) sealed in the implementation but not sealed in the contract.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableContextAttribute' exists on 'AutoMapper.QueryableExtensions.Extensions.ProjectTo(System.Linq.IQueryable, System.Type, AutoMapper.IConfigurationProvider)' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableContextAttribute' exists on 'AutoMapper.QueryableExtensions.Extensions.ProjectTo(System.Linq.IQueryable, System.Type, AutoMapper.IConfigurationProvider, System.Collections.Generic.IDictionary<System.String, System.Object>, System.String[])' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableAttribute' exists on parameter 'parameters' on member 'AutoMapper.QueryableExtensions.Extensions.ProjectTo(System.Linq.IQueryable, System.Type, AutoMapper.IConfigurationProvider, System.Collections.Generic.IDictionary<System.String, System.Object>, System.String[])' in the contract but not the implementation.
Expand All @@ -52,4 +69,4 @@ CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableAttri
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableContextAttribute' exists on 'AutoMapper.QueryableExtensions.Extensions.ProjectTo<TDestination>(System.Linq.IQueryable, AutoMapper.IConfigurationProvider, System.Object, System.Linq.Expressions.Expression<System.Func<TDestination, System.Object>>[])' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableAttribute' exists on parameter 'parameters' on member 'AutoMapper.QueryableExtensions.Extensions.ProjectTo<TDestination>(System.Linq.IQueryable, AutoMapper.IConfigurationProvider, System.Object, System.Linq.Expressions.Expression<System.Func<TDestination, System.Object>>[])' in the contract but not the implementation.
CannotRemoveAttribute : Attribute 'System.Runtime.CompilerServices.NullableAttribute' exists on generic param 'TDestination' on member 'AutoMapper.QueryableExtensions.Extensions.ProjectTo<TDestination>(System.Linq.IQueryable, AutoMapper.IConfigurationProvider, System.Object, System.Linq.Expressions.Expression<System.Func<TDestination, System.Object>>[])' in the contract but not the implementation.
Total Issues: 53
Total Issues: 70
4 changes: 2 additions & 2 deletions src/AutoMapper/AutoMapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<Summary>A convention-based object-object mapper.</Summary>
<Description>A convention-based object-object mapper.</Description>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>AutoMapper</AssemblyName>
<AssemblyOriginatorKeyFile>..\..\AutoMapper.snk</AssemblyOriginatorKeyFile>
Expand Down Expand Up @@ -38,7 +38,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
<PackageReference Include="MinVer" Version="4.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="7.0.0-beta.22074.1" PrivateAssets="All" />
Expand Down
7 changes: 5 additions & 2 deletions src/AutoMapper/ConstructorMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ public bool ApplyMap(TypeMap typeMap, IncludedMember includedMember = null)
[EditorBrowsable(EditorBrowsableState.Never)]
public class ConstructorParameterMap : MemberMap
{
public ConstructorParameterMap(TypeMap typeMap, ParameterInfo parameter, MemberInfo[] sourceMembers) : base(typeMap)
public ConstructorParameterMap(TypeMap typeMap, ParameterInfo parameter, MemberInfo[] sourceMembers) : base(typeMap, parameter.ParameterType)
{
Parameter = parameter;
if(DestinationType.IsByRef)
{
DestinationType = DestinationType.GetElementType();
}
if (sourceMembers.Length > 0)
{
MapByConvention(sourceMembers);
Expand All @@ -80,7 +84,6 @@ public ConstructorParameterMap(TypeMap typeMap, ParameterInfo parameter, MemberI
}
}
public ParameterInfo Parameter { get; }
public override Type DestinationType => Parameter.ParameterType;
public override IncludedMember IncludedMember { get; protected set; }
public override MemberInfo[] SourceMembers { get; set; }
public override string DestinationName => Parameter.Name;
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/AssignableMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AutoMapper.Internal.Mappers;

public class AssignableMapper : IObjectMapper
public sealed class AssignableMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.DestinationType.IsAssignableFrom(context.SourceType);
public Expression MapExpression(IGlobalConfiguration configuration, ProfileMap profileMap,
Expand Down
13 changes: 6 additions & 7 deletions src/AutoMapper/Mappers/CollectionMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Collections.Specialized;
namespace AutoMapper.Internal.Mappers;
using static ReflectionHelper;
public class CollectionMapper : IObjectMapper
public sealed class CollectionMapper : IObjectMapper
{
static readonly MethodInfo IListAdd = typeof(IList).GetMethod(nameof(IList.Add));
public TypePair? GetAssociatedTypes(TypePair context) => new(GetElementType(context.SourceType), GetElementType(context.DestinationType));
Expand Down Expand Up @@ -241,24 +241,23 @@ bool MustMap(Type sourceType, Type destinationType) => !destinationType.IsAssign
}
public readonly struct MultidimensionalArrayFiller(Array destination)
{
private readonly int[] _indices = new int[destination.Rank];
private readonly Array _destination = destination;
readonly int[] _indices = new int[destination.Rank];
public void NewValue(object value)
{
var dimension = _destination.Rank - 1;
var dimension = destination.Rank - 1;
var changedDimension = false;
while (_indices[dimension] == _destination.GetLength(dimension))
while (_indices[dimension] == destination.GetLength(dimension))
{
_indices[dimension] = 0;
dimension--;
if (dimension < 0)
{
throw new InvalidOperationException("Not enough room in destination array " + _destination);
throw new InvalidOperationException("Not enough room in destination array " + destination);
}
_indices[dimension]++;
changedDimension = true;
}
_destination.SetValue(value, _indices);
destination.SetValue(value, _indices);
if (changedDimension)
{
_indices[dimension + 1]++;
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ConstructorMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class ConstructorMapper : IObjectMapper
public sealed class ConstructorMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => GetConstructor(context.SourceType, context.DestinationType) != null;
private static ConstructorInfo GetConstructor(Type sourceType, Type destinationType) =>
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ConversionOperatorMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class ConversionOperatorMapper : IObjectMapper
public sealed class ConversionOperatorMapper : IObjectMapper
{
private readonly string _operatorName;
public ConversionOperatorMapper(string operatorName) => _operatorName = operatorName;
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ConvertMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class ConvertMapper : IObjectMapper
public sealed class ConvertMapper : IObjectMapper
{
public static bool IsPrimitive(Type type) => type.IsPrimitive || type == typeof(string) || type == typeof(decimal);
public bool IsMatch(TypePair types) => (types.SourceType == typeof(string) && types.DestinationType == typeof(DateTime)) ||
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/EnumToEnumMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class EnumToEnumMapper : IObjectMapper
public sealed class EnumToEnumMapper : IObjectMapper
{
private static readonly MethodInfo TryParseMethod = typeof(Enum).StaticGenericMethod("TryParse", parametersCount: 3);
public bool IsMatch(TypePair context) => context.IsEnumToEnum();
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/FromDynamicMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Microsoft.CSharp.RuntimeBinder;
using Binder = Microsoft.CSharp.RuntimeBinder.Binder;
namespace AutoMapper.Internal.Mappers;
public class FromDynamicMapper : IObjectMapper
public sealed class FromDynamicMapper : IObjectMapper
{
private static readonly MethodInfo MapMethodInfo = typeof(FromDynamicMapper).GetStaticMethod(nameof(Map));
private static object Map(object source, object destination, Type destinationType, ResolutionContext context, ProfileMap profileMap)
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/FromStringDictionaryMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using StringDictionary = System.Collections.Generic.IDictionary<string, object>;
namespace AutoMapper.Internal.Mappers;
public class FromStringDictionaryMapper : IObjectMapper
public sealed class FromStringDictionaryMapper : IObjectMapper
{
private static readonly MethodInfo MapDynamicMethod = typeof(FromStringDictionaryMapper).GetStaticMethod(nameof(MapDynamic));
public bool IsMatch(TypePair context) => typeof(StringDictionary).IsAssignableFrom(context.SourceType);
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/KeyValueMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class KeyValueMapper : IObjectMapper
public sealed class KeyValueMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => IsKeyValue(context.SourceType) && IsKeyValue(context.DestinationType);
public static bool IsKeyValue(Type type) => type.IsGenericType(typeof(KeyValuePair<,>));
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/NullableDestinationMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AutoMapper.Internal.Mappers;

public class NullableDestinationMapper : IObjectMapper
public sealed class NullableDestinationMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.DestinationType.IsNullableType();
public Expression MapExpression(IGlobalConfiguration configuration, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression) =>
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/NullableSourceMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AutoMapper.Internal.Mappers;

public class NullableSourceMapper : IObjectMapper
public sealed class NullableSourceMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.SourceType.IsNullableType();
public Expression MapExpression(IGlobalConfiguration configuration, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression) =>
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ParseStringMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AutoMapper.Internal.Mappers;

public class ParseStringMapper : IObjectMapper
public sealed class ParseStringMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.SourceType == typeof(string) && HasParse(context.DestinationType);
static bool HasParse(Type type) => type == typeof(Guid) || type == typeof(TimeSpan) || type == typeof(DateTimeOffset);
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/StringToEnumMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Runtime.Serialization;
namespace AutoMapper.Internal.Mappers;
public class StringToEnumMapper : IObjectMapper
public sealed class StringToEnumMapper : IObjectMapper
{
private static readonly MethodInfo EqualsMethod = typeof(StringToEnumMapper).GetMethod(nameof(StringCompareOrdinalIgnoreCase));
private static readonly MethodInfo ParseMethod = typeof(Enum).StaticGenericMethod("Parse", parametersCount: 2);
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ToDynamicMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Microsoft.CSharp.RuntimeBinder;
using Binder = Microsoft.CSharp.RuntimeBinder.Binder;
namespace AutoMapper.Internal.Mappers;
public class ToDynamicMapper : IObjectMapper
public sealed class ToDynamicMapper : IObjectMapper
{
private static readonly MethodInfo MapMethodInfo = typeof(ToDynamicMapper).GetStaticMethod(nameof(Map));
private static object Map(object source, object destination, Type destinationType, ResolutionContext context, ProfileMap profileMap)
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ToStringDictionaryMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class ToStringDictionaryMapper : IObjectMapper
public sealed class ToStringDictionaryMapper : IObjectMapper
{
private static readonly MethodInfo MembersDictionaryMethodInfo = typeof(ToStringDictionaryMapper).GetStaticMethod(nameof(MembersDictionary));
public bool IsMatch(TypePair context) => typeof(IDictionary<string, object>).IsAssignableFrom(context.DestinationType);
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/ToStringMapper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
namespace AutoMapper.Internal.Mappers;
public class ToStringMapper : IObjectMapper
public sealed class ToStringMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.DestinationType == typeof(string);
public Expression MapExpression(IGlobalConfiguration configuration, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression)
Expand Down
2 changes: 1 addition & 1 deletion src/AutoMapper/Mappers/UnderlyingEnumTypeMapper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AutoMapper.Internal.Mappers;

public class UnderlyingTypeEnumMapper : IObjectMapper
public sealed class UnderlyingTypeEnumMapper : IObjectMapper
{
public bool IsMatch(TypePair context) => context.IsEnumToUnderlyingType() || context.IsUnderlyingTypeToEnum();
public Expression MapExpression(IGlobalConfiguration configuration, ProfileMap profileMap,
Expand Down
6 changes: 3 additions & 3 deletions src/AutoMapper/MemberMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace AutoMapper;
public class MemberMap : IValueResolver
{
private protected Type _sourceType;
protected MemberMap(TypeMap typeMap) => TypeMap = typeMap;
internal static readonly MemberMap Instance = new(null);
protected MemberMap(TypeMap typeMap, Type destinationType) => (TypeMap, DestinationType) = (typeMap, destinationType);
internal static readonly MemberMap Instance = new(null, null);
public TypeMap TypeMap { get; protected set; }
public LambdaExpression CustomMapExpression => Resolver?.ProjectToExpression;
public bool IsResolveConfigured => Resolver != null && Resolver != this;
Expand All @@ -22,7 +22,7 @@ public void SetResolver(IValueResolver resolver)
public virtual MemberInfo[] SourceMembers { get => []; set { } }
public virtual IncludedMember IncludedMember { get => default; protected set { } }
public virtual string DestinationName => default;
public virtual Type DestinationType { get => default; protected set { } }
public Type DestinationType { get; protected set; }
public virtual TypePair Types() => new(SourceType, DestinationType);
public bool CanResolveValue => !Ignored && Resolver != null;
public bool IsMapped => Ignored || Resolver != null;
Expand Down
Loading
Loading