p1eXu5.AutoProfile 11.1.4

dotnet add package p1eXu5.AutoProfile --version 11.1.4                
NuGet\Install-Package p1eXu5.AutoProfile -Version 11.1.4                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="p1eXu5.AutoProfile" Version="11.1.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add p1eXu5.AutoProfile --version 11.1.4                
#r "nuget: p1eXu5.AutoProfile, 11.1.4"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install p1eXu5.AutoProfile as a Cake Addin
#addin nuget:?package=p1eXu5.AutoProfile&version=11.1.4

// Install p1eXu5.AutoProfile as a Cake Tool
#tool nuget:?package=p1eXu5.AutoProfile&version=11.1.4                

AutoProfile.

<em>Custom AutoMapper attributes and profiler.</em>

Package Versions
p1eXu5.AutoProfile NuGet
p1eXu5.AutoProfile NuGet
p1eXu5.AutoProfile NuGet
p1eXu5.AutoProfile NuGet
p1eXu5.AutoProfile NuGet

<br/>

Mapping configurations.

see test project for more examples

1. Using map configuration factory method:

<br/>

[MapTo(typeof(Model), 
    MapFactory = nameof(CreateMapMethod), 
    IncludeAllDerived = true, 
    ReverseMap = true,
    IncludeAllDerivedForReverse = true)]
[MapFrom(typeof(Model2), MapFactory = nameof(CreateMapMethod))]
public class Dto
{
    ...

    public IMappingExpression<Dto, Model> CreateMapMethod(IAutoProfile profile)
    {
        return
            profile.Instance.CreateMap<Dto, Model>(MemberList.Source);
    }

    public static IMappingExpression<Model2, Dto> StaticCreateMapMethod(IAutoProfile profile)
    {
        return
            profile.Instance.CreateMap<Model2, Dto>(MemberList.Source);
    }
}

If factory method is located in other type use MapFactoryType attribute property.

<br/>

2. Using reverse map factory configuration method:

<br/>

[MapTo( typeof(IApplicationUser), 
    IncludeAllDerived = true, 
    IncludeAllDerivedForReverse = true,
    MapFactory = nameof(UserDtoBase.CreateMap), 
    ReverseMapFactory = nameof(UserDtoBase.CreateReverseMap))]
public class UserDtoBase
{
    public IMappingExpression<UserDtoBase, IApplicationUser> CreateMap(DerivedAutoProfile profile)
    {
        return
            profile.Instance.CreateMap<UserDtoBase, IApplicationUser>(MemberList.Source)
                .ForMember(au => au.FirstName, opt => opt.MapFrom((dto, au) => TextCipherSet.Encrypt( dto.FirstName, profile.PassPhrase)))
                .ForMember(au => au.LastName, opt => opt.MapFrom((dto, au) => TextCipherSet.Encrypt( dto.LastName, profile.PassPhrase)));
    }

    // expr and profile can have any order in parameters
    public IMappingExpression<IApplicationUser, UserDtoBase> CreateReverseMap( 
        IMappingExpression<UserDtoBase, IApplicationUser> expr, 
        DerivedAutoProfile profile)
    {
        return
            expr.ReverseMap()
                .ForMember(dto => dto.FirstName, opt => opt.MapFrom((au, dto) => TextCipherSet.Decrypt( au.FirstName, profile.PassPhrase)))
                .ForMember(dto => dto.LastName, opt => opt.MapFrom((au, dto) => TextCipherSet.Decrypt( au.LastName, profile.PassPhrase)));
    }
}

<br/>

3. Ignoring property.

<br/>

Ignoring destination property:

<br/>

[MapFrom(typeof(IModelA))]
[MapFrom(typeof(Model) /*, ...*/)]
public class ViewModel
{
    [Ignore]
    public IList<string> RoleNames { get; set; } = default!;
}

<br/>

[MapTo(typeof(ModelA))]
public class ViewModel...
{
    public IList<string> RoleNames { get; set; } = default!;
}

public class ModelA...
{
    [Ignore]
    public IList<string> RoleNames { get; set; } = default!;
}

<br/>

Ignoring source property:

<br/>

[MapTo(typeof(IModelA))]
public class ViewModel
{
    [Ignore]
    public IList<string> RoleNames { get; set; } = default!;
}

<br/>

[MapFrom(typeof(ModelA))]
public class ViewModel
{
    public IList<string> RoleNames { get; set; } = default!;
}

public class ModelA
{
    [Ignore]
    public IList<string> RoleNames { get; set; } = default!;
}

<br/>

4. OppositeAttribute usage:

<br/>

[MapTo(typeof(IApplicationUser))]
[MapFrom(typeof(IApplicationUser))]
public class UserUpdateDto : UserDto, IEntityIdDto<string>
{
    [Opposite(nameof(IApplicationUser.UserTools))]
    public ICollection<EntityIdDto>? Tools { get; set; }
}

<br/>

<b>Warning! There is an workaround to use with immutable record:</b>

<br/>

  1. Define private parameterless constructor

  2. Add private init

    public record RecordModel
    {
        private RecordModel()
        { }
    
        public RecordModel(string oppositeProp) : this()
        {
            this.OppositeProp = oppositeProp;
        }
    
        public string OppositeProp { get; private init; }
    }
    

<br/>

Usage cases

<br/>

1. Configure in the ASP.NET Core:

<br/>

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection -Version 11.0.0

builder.Services.AddAutoMapper(
    (serviceProvider, cfg) =>
    { 
        var logger = serviceProvider.GetRequiredService<ILogger<AutoProfile>>();
        var profile = new AutoProfile(typeof(Model), logger);
        cfg.AddProfile(profile.Configure());
    },
     new Type[0]);

<br/>

2. For testing of certain maps:

<br/>

public abstract class AutoMapperTestsBase
{
    protected IMapper Mapper { get; private set; } = default!;

    protected virtual ICollection<Type> MappingTypes { get; } = Array.Empty<Type>();

    [OneTimeSetUp]
    public void Initialize()
    {
        AutoProfile autoProfile = new AutoProfile(
            MockLoggerFactories.GetMockILogger<AutoProfile>(TestContext.WriteLine).Object,
            new AutoProfileOptions(ProcessMapAttributesFromAssembly: false));

        foreach (var type in MappingTypes) {
            autoProfile.CreateMaps(type);
        }

        var conf = new MapperConfiguration(cfg => cfg.AddProfile(autoProfile.Configure()));
        conf.AssertConfigurationIsValid();

        Mapper = conf.CreateMapper();
    }
}

<br/>

Other known issuers & workarounds.

<br/>

  • When a collection is mapped with resolver additional configuration is needed or AssertConfigurationIsValid() is failed (Automapper 9.0.0 bug):

    public IMappingExpression<ProjectDto, Project> CreateMap(IAutoProfile profile)
    {
        return
            profile.Instance.CreateMap<Dto, Model>(MemberList.Source)
                .ForMember(model => model.Collection, opt => opt.MapFrom(dto => dto.Collection))
                .ForMember(model => model.Collection,
                    opt => {
                        opt.MapFrom<FooResolver, ICollection<FooType>?>(dto => dto.Collection);
                    });
    }
    
  • In some cases you'll have to use both MapTo and MapFrom attribute instead of using ReverseMap = true only or AssertConfigurationIsValid() is failed (Automapper 9.0.0 bug).

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
11.1.4 385 5/16/2023
11.1.3 1,251 7/13/2022
11.1.2 649 5/24/2022
11.0.1 447 4/9/2022
10.1.5.2 892 12/3/2021
0.1.0 419 10/26/2020