Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0caa9b7
feat: add MapUsing override Type mapping setting (#985)
DocSvartz Jul 22, 2026
272d395
feat: add Custom Default Value for destination Type (#1001)
DocSvartz Jul 23, 2026
acd3e5a
fix: mark SkipSettings setting setter as Obsolete
DocSvartz Jul 27, 2026
4bc2a2e
chore: Bump version to v10.1.0-pre01
DocSvartz Jul 27, 2026
7857b0c
feat: add SkipDestinationTransforms()
DocSvartz Jul 28, 2026
a246b7a
fix: replace Expression.Default to CreateDefault(arg)
DocSvartz Jul 29, 2026
5bcfadd
fix: fix using Custom DefaultValue to Ctor
DocSvartz Jul 29, 2026
44d3345
feat(test): add test using custom DefaultValue in Ctor params
DocSvartz Jul 31, 2026
748e491
fix: refactoring get ovveride settings
DocSvartz Jul 31, 2026
2edfbf9
feat: add ExtraSource custom Settings Supported
DocSvartz Jul 31, 2026
2d64de7
fix: drop Ctor param NullPropagation overhead
DocSvartz Aug 3, 2026
3acfd82
fix: add replacer to ExtraSource params
DocSvartz Aug 4, 2026
44c8045
fix: src param replace
DocSvartz Aug 5, 2026
78bafc1
feat: add ApplyResolversOnly
DocSvartz Aug 5, 2026
2f4c5d6
fix: extra params apply
DocSvartz Aug 5, 2026
b5887cf
feat: add Remap Setter
DocSvartz Aug 5, 2026
854f74a
fix: refactoring ReMap setter
DocSvartz Aug 6, 2026
f3e348e
fix: custom default
DocSvartz Aug 6, 2026
85e558f
feat: update null propagation
DocSvartz Aug 6, 2026
810032c
Merge pull request #1006 from DocSvartz/10.1.---feat-null-propagation
DocSvartz Aug 10, 2026
b96b98e
chore: Bump version to v10.1.0-pre02
DocSvartz Aug 10, 2026
1f9f89c
feat: Improvements for MapsterTool GenerateMappers
DocSvartz Aug 19, 2026
de497a0
feat: add GeneratedMapperAttribute and test
DocSvartz Aug 19, 2026
efb4ddd
feat: add helpers file created param
DocSvartz Aug 19, 2026
1caf391
Merge branch 'v10.1.0' into development
DocSvartz Aug 19, 2026
6312229
feat: add random
DocSvartz Aug 19, 2026
2a7509c
feat: add supported generate mappers for internal interfaces and publ…
DocSvartz Aug 20, 2026
83e2750
fix: refactoring attribute impl
DocSvartz Aug 20, 2026
7cf5553
fix: skip explicit interface implimentation if using only public way:
DocSvartz Aug 20, 2026
f80678e
fix: refactoring RandomNamespaceGenerator
DocSvartz Aug 25, 2026
1b263b9
fix: refactoring helpers generation
DocSvartz Aug 25, 2026
4c45b1e
chore: Merge pull request #1011 from DocSvartz/feat-MapsterTool--publish
DocSvartz Aug 25, 2026
6cccb63
chore: Bump version to v10.0.13-pre01
DocSvartz Aug 25, 2026
a2bb32f
Revert "Improvements for Mapster Tool "
DocSvartz Aug 25, 2026
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 src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<!-- Properties related to build/pack -->
<IsPackable>false</IsPackable>
<Version>10.0.12</Version>
<Version>10.0.13-pre01</Version>
<MapsterPluginsTFMs>netstandard2.0;net10.0;net9.0;net8.0</MapsterPluginsTFMs>
<MapsterTFMs>netstandard2.0;net10.0;net9.0;net8.0</MapsterTFMs>
<MapsterEFCoreTFMs>net10.0;net9.0;net8.0</MapsterEFCoreTFMs>
Expand Down
1 change: 1 addition & 0 deletions src/Mapster.Core/Enums/MapType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public enum MapType
MapToTarget = 2,
Projection = 4,
ApplyNullPropagation = 8,
CtorParam = 16,
}
}
4 changes: 2 additions & 2 deletions src/Mapster.EF6/TypeAdapterBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ public static ITypeAdapterBuilder<TSource> EntityFromContext<TSource>(this IType
var getters = keys.Select(key => arg.DestinationType.GetProperty(key))
.Select(prop => new PropertyModel(prop))
.Select(model => arg.Settings.ValueAccessingStrategies
.Select(s => s(src, model, arg))
.Select(s => s((ResolverSourceInput)src, model, arg))
.FirstOrDefault(exp => exp != null))
.Where(exp => exp != null)
.Select(exp => Expression.Convert(exp, typeof(object)))
.Select(exp => Expression.Convert(exp.Exp, typeof(object)))
.ToArray();
if (getters.Length != keys.Length)
throw new InvalidOperationException($"Cannot get key for sourceType={arg.SourceType.Name}, destinationType={arg.DestinationType.Name}");
Expand Down
4 changes: 2 additions & 2 deletions src/Mapster.EFCore/TypeAdapterBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public static ITypeAdapterBuilder<TSource> EntityFromContext<TSource>(this IType
var getters = keys.Select(key => arg.DestinationType.GetProperty(key))
.Select(prop => new PropertyModel(prop!))
.Select(model => arg.Settings.ValueAccessingStrategies
.Select(s => s(src, model, arg))
.Select(s => s((ResolverSourceInput)src, model, arg))
.FirstOrDefault(exp => exp != null))
.Where(exp => exp != null)
.Select(exp => Expression.Convert(exp, typeof(object)))
.Select(exp => Expression.Convert(exp.Exp, typeof(object)))
.ToArray();
if (getters.Length != keys.Length)
throw new InvalidOperationException($"Cannot get key for sourceType={arg.SourceType.Name}, destinationType={arg.DestinationType.Name}");
Expand Down
327 changes: 327 additions & 0 deletions src/Mapster.Tests/WhenMapUsingOverrideTypesSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Mapster.Tests
{
[TestClass]
public class WhenMapUsingOverrideTypesSettings
{
[TestMethod]
public void OverrideDestinationTramsformIsWorked()
{
var config = new TypeAdapterConfig();
config.Default.AddDestinationTransform(DestinationTransform.EmptyCollectionIfNull);

config
.NewConfig<CollectionPocoOverride, CollectionDtoOverride>()
.MapUsing(src => src.Children, dest => dest.Children,
cfg =>
{
cfg.SkipDestinationTransforms();
})
.MapUsing(src => src.Array, dest => dest.Array,
cfg =>
{
cfg
.ReConfigurate()
.MapWith(x => x ?? new[] { 42 });
});


var source = new CollectionPocoOverride();
var destination = source.Adapt<CollectionDtoOverride>(config);

destination.MultiDimentionalArray.Length.ShouldBe(0);
destination.ChildDict.Count.ShouldBe(0);
destination.Set.Count.ShouldBe(0);


destination.Children.ShouldBeNull(); // Destination Transforms from global context settings is skipped for this property
destination.Array[0].ShouldBe(42); // Custom converter for types is worked, Destination Transforms is not achievable because the custom converter never returns null


var destWithNotTypesSettingOverride = new CollectionPocoOverride().Adapt<CollectionDtoWithArray>(config);

// Destination Transforms correct work from other mapping types
destWithNotTypesSettingOverride.Array.Length.ShouldBe(0);
}

[TestMethod]
public void UsingDefaultValueIsWorked()
{
var config = new TypeAdapterConfig();

config.ForDestinationType<int>()
.DefaultValue(x => 32);

config.ForDestinationType<int?>()
.DefaultValue(x=>42);

int? src = null;
var srcInsaider = new NullableIntInsaider() { Data = null };


var resultCD = src.Adapt<int>(config);
var resultCDInsaider = srcInsaider.Adapt<NullableIntInsaider>(config);

resultCD.ShouldBe(32);
resultCDInsaider.Data.ShouldBe(42);

config.
NewConfig<NullableIntInsaider, NullableIntInsaiderReconfig>()
.MapUsing(dest => dest.Data, src => src.Data, cfg =>
{
cfg.ReConfigurate()
.DefaultValue(x => 35);
});

var resultCDInsaiderReconfig = srcInsaider.Adapt<NullableIntInsaiderReconfig>(config);

resultCDInsaiderReconfig.Data.ShouldBe(35);
}

[TestMethod]
public void CustomDefaultValueIsWorkedWhenUsingAsCtorParam()
{
var config = new TypeAdapterConfig();

config.ForDestinationType<int?>()
.DefaultValue(x => 42);

config.
NewConfig<NullableIntInsaider, NullableIntCtorParam>()
.MapUsing(dest => dest.Data, src => src.Data, cfg =>
{
cfg.ReConfigurate()
.DefaultValue(x => 35);
});

var src = new NullableIntInsaider() { Data = null };

var result = src.Adapt<NullableIntCtorParam>(config);

result.Data.ShouldBe(35);
}

[TestMethod]
public void ExtraSourceUsingCustomConfig()
{
var config = new TypeAdapterConfig();
config.Default.AddDestinationTransform(DestinationTransform.EmptyCollectionIfNull);
config.NewConfig<SourceFlattentInsaider, DestinationFlattentData>()
.MapUsing(dest=> dest, src => src.SrcData, cfg =>
{
cfg.SkipDestinationTransforms()
.ReConfigurate()
.Map(dest=>dest.Data, src => 42)
.MapUsing(dest => dest.Collection, src => src.Collection, cfg =>
{
cfg
.SkipDestinationTransforms();
})
;
});

var src = new SourceFlattentInsaider() { SrcData = new() { Value = "Hello" } };

var result = src.Adapt<DestinationFlattentData>(config);

result.Collection.ShouldBeNull();
result.Data.ShouldBe(42);
}


[TestMethod]
public void ReMapSettersIsWorked()
{
var config = new TypeAdapterConfig();
config.Default.AddDestinationTransform(DestinationTransform.EmptyCollectionIfNull);
config.ForDestinationType<DestinationFlattentData>()
.Ignore(x => x.Value)
.Ignore(x => x.Data);
config.NewConfig<SourceFlattentInsaider, DestinationFlattentData>()
.ReMap(dest => dest, src => src.SrcData, true);
config.NewConfig<RemapMemberMappings, DestinationFlattentData>()
.ReMap(dest => dest.Data, src => src.Data);

var src = new SourceFlattentInsaider() { SrcData = new() { Value = "Hello", Data = 42 } };
var reMapSrc = new RemapMemberMappings { Data = 21, Value = "World" };



var result = src.Adapt<DestinationFlattentData>(config);

result.Collection.ShouldBeNull();
result.Value.ShouldBe("Hello");
result.Data.ShouldBe(42);

var reMapResut = reMapSrc.Adapt<DestinationFlattentData>(config);

reMapResut.Data.ShouldBe(21);
reMapResut.Value.ShouldBe(default);
}

[TestMethod]
public void ApplyPropagantionUsingDeepSrcAnalize()
{
var config = new TypeAdapterConfig();

config.NewConfig<Source1004, Destination1004>()
.Map(dest => dest.ProductNames, src => src.Products.Select(x => x.Name).ToArray());

config.NewConfig<Source1004, DestinationCtor1004>()
.Map(dest => dest.ProductNames, src => src.Products.Select(x => x.Name).ToArray());

config.NewConfig<NullableStrings, NullableStringsDest>()
.Map(dest => dest.Result, src => $"{src.Value1.ToString()}");

config.NewConfig<NullableStrings, NullableStringsDestCtor>()
.Map(dest => dest.Result, src => $"{src.Value1.ToString()}");

var src = new Source1004();
var srcStrings = new NullableStrings();

//var str = src.BuildAdapter(config).CreateMapExpression<DestinationCtor1004>();
//var str2 = src.BuildAdapter(config).CreateMapExpression<NullableStringsDestCtor>();

Should.NotThrow(() =>
{
src.Adapt<Destination1004>(config);
src.Adapt<DestinationCtor1004>(config);

srcStrings.Adapt<NullableStringsDest>(config);
srcStrings.Adapt<NullableStringsDestCtor>(config);
});
}

#region TestClasses

class Source1004
{
public Product1004[]? Products { get; set; }
}

class Product1004
{
public required string Name { get; set; }
}

class Destination1004
{
public string[]? ProductNames { get; set; }
}

class DestinationCtor1004
{
public DestinationCtor1004(string[]? productNames)
{
ProductNames = productNames;
}

public string[]? ProductNames { get; }
}

public class NullableStrings
{
public string Value1 { get; set; }

public string Value2 { get; set; }
}

public class NullableStringsDest
{
public string Result { get; set; }
}
public class NullableStringsDestCtor
{
public NullableStringsDestCtor(string result)
{
Result = result;
}

public string Result { get;}
}

public class RemapMemberMappings
{
public int Data { get; set; }
public string Value { get; set; }
}

public class DestinationFlattentData
{
public int Data { get; set; }
public string Value { get; set; }
public List<string> Collection { get; set; }
}

public class SourceFlattentData
{
public int Data { get; set; }
public string Value { get; set; }
public List<string> Collection { get; set; }
}

public class SourceFlattentInsaider
{
public SourceFlattentData SrcData { get; set; }
}

public class NullableIntCtorParam
{
public NullableIntCtorParam(int? data)
{
Data = data;
}
public int? Data { get; }
}


public class NullableIntInsaider
{
public int? Data { get; set; }
}

public class NullableIntInsaiderReconfig
{
public int? Data { get; set; }
}
class CollectionPocoWithArray
{
public int[] Array { get; set; }
}

class CollectionDtoWithArray
{
public int[] Array { get; set; }
}

class CollectionPocoOverride
{
public Guid Id { get; set; }
public string Name { get; set; }

public List<ChildPoco> Children { get; set; }
public int[] Array { get; set; }
public double[,] MultiDimentionalArray { get; set; }
public Dictionary<string, ChildPoco> ChildDict { get; set; }
public HashSet<string> Set { get; set; }
}

class CollectionDtoOverride
{
public Guid Id { get; set; }
public string Name { get; set; }

public IReadOnlyList<ChildDto> Children { get; internal set; }
public int[] Array { get; set; }
public double[,] MultiDimentionalArray { get; set; }
public IReadOnlyDictionary<string, ChildDto> ChildDict { get; set; }
public ISet<string> Set { get; set; }
}
#endregion TestClasses
}
}
Loading
Loading