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
75 changes: 75 additions & 0 deletions src/Mapster.Tests/WhenUseTempAdapterConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;

namespace Mapster.Tests
{

public record SourceDto(string Name, int Age);
public record DestinationDto(long Id, string Name, int Age);

[TestClass]
public class WhenUseTempAdapterConfig
{
[TestMethod]
public void Adapt_TemporaryConfig_ShouldMapInitOnlyProperties()
{
// Arrange
var source = new SourceDto("Alice", 30);
long id = 42;

// Act
var result = source.Adapt<DestinationDto>(cfg =>
{
cfg.NewConfig<SourceDto, DestinationDto>()
.Map(dest => dest.Id, src => id);
});

// Assert
result.Name.ShouldBe("Alice");
result.Age.ShouldBe(30);
result.Id.ShouldBe(42);
}

[TestMethod]
public void Adapt_WithSetter_ShouldMapInitOnlyProperties()
{
// Arrange
var source = new SourceDto("Bob", 25);
long id = 99;

// Act
var result = source.Adapt<SourceDto, DestinationDto>(setter =>
{
setter.Map(dest => dest.Id, src => id);
});

// Assert
result.Name.ShouldBe("Bob");
result.Age.ShouldBe(25);
result.Id.ShouldBe(99);
}

[TestMethod]
public void Adapt_TemporaryConfig_ShouldNotModifyGlobalSettings()
{
// Arrange
var source = new SourceDto("Charlie", 40);
long id = 123;

var globalMap = TypeAdapterConfig.GlobalSettings.GetMapFunction<SourceDto, DestinationDto>();

// Act
var result = source.Adapt<SourceDto, DestinationDto>(setter =>
{
setter.Map(dest => dest.Id, src => id);
});

// Assert
var original = globalMap(source); // mapping via GlobalSettings
original.Id.ShouldBe(default(long)); // GlobalSettings unaffected
original.Name.ShouldBe("Charlie");
original.Age.ShouldBe(40);
}

}
}
36 changes: 36 additions & 0 deletions src/Mapster/TypeAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,42 @@ public static TDestination ValidateAndAdapt<TSource, TDestination>(this TSource
}
return source.Adapt<TDestination>(config);
}


/// <summary>
/// Adapt the source object to a destination type using a temporary configuration.
/// A new TypeAdapterConfig is created for this call, ensuring GlobalSettings remain unchanged.
/// Safe for init-only properties and record types.
/// </summary>
/// <typeparam name="TDestination">Destination type.</typeparam>
/// <param name="source">Source object to adapt.</param>
/// <param name="configAction">Action to customize the temporary config.</param>
/// <returns>Adapted destination object of type TDestination.</returns>
public static TDestination Adapt<TDestination>(this object? source, Action<TypeAdapterConfig> configAction)
{
var config = TypeAdapterConfig.GlobalSettings.Clone();
configAction(config);
return source.Adapt<TDestination>(config);
}

/// <summary>
/// Adapt the source object from TSource to TDestination using a dedicated TypeAdapterSetter.
/// A temporary TypeAdapterConfig is created and configured via the setter.
/// Safe for init-only properties and record types, without modifying GlobalSettings.
/// </summary>
/// <typeparam name="TSource">Source type.</typeparam>
/// <typeparam name="TDestination">Destination type.</typeparam>
/// <param name="source">Source object to adapt.</param>
/// <param name="configAction">Action to customize the TypeAdapterSetter.</param>
/// <returns>Adapted destination object of type TDestination.</returns>
public static TDestination Adapt<TSource, TDestination>(this object? source, Action<TypeAdapterSetter<TSource, TDestination>> configAction)
{
var config = TypeAdapterConfig.GlobalSettings.Clone();
var setter = config.ForType<TSource, TDestination>();
configAction(setter);
setter.Settings.Resolvers.Reverse();
return source.Adapt<TDestination>(config);
}
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "<Pending>")]
Expand Down
Loading