Skip to content

Commit e6f3abf

Browse files
committed
Extracting MaptoTarget adapters to a file TypeAdapterToTarget.cs
1 parent 06e733b commit e6f3abf

File tree

3 files changed

+8
-305
lines changed

3 files changed

+8
-305
lines changed

src/Mapster/Mapster.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@
2929
<ItemGroup>
3030
<ProjectReference Include="..\Mapster.Core\Mapster.Core.csproj" />
3131
</ItemGroup>
32+
<ItemGroup>
33+
<Folder Include="TypeAdapters\" />
34+
</ItemGroup>
3235
</Project>

src/Mapster/TypeAdapter.cs

Lines changed: 2 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Mapster
99
{
10-
public static class TypeAdapter
10+
public static partial class TypeAdapter
1111
{
1212
public static ITypeAdapterBuilder<TSource> BuildAdapter<TSource>(this TSource source)
1313
{
@@ -75,61 +75,6 @@ public static TDestination Adapt<TSource, TDestination>(this TSource source, Typ
7575
return fn(source);
7676
}
7777

78-
/// <summary>
79-
/// Adapt the source object to the existing destination object.
80-
/// </summary>
81-
/// <typeparam name="TSource">Source type.</typeparam>
82-
/// <typeparam name="TDestination">Destination type.</typeparam>
83-
/// <param name="source">Source object to adapt.</param>
84-
/// <param name="destination">The destination object to populate.</param>
85-
/// <returns>Adapted destination type.</returns>
86-
public static TDestination Adapt<TSource, TDestination>(this TSource source, TDestination destination)
87-
{
88-
return Adapt(source, destination, TypeAdapterConfig.GlobalSettings);
89-
}
90-
91-
/// <summary>
92-
/// Adapt the source object to the existing destination object.
93-
/// </summary>
94-
/// <typeparam name="TSource">Source type.</typeparam>
95-
/// <typeparam name="TDestination">Destination type.</typeparam>
96-
/// <param name="source">Source object to adapt.</param>
97-
/// <param name="destination">The destination object to populate.</param>
98-
/// <param name="config">Configuration</param>
99-
/// <returns>Adapted destination type.</returns>
100-
public static TDestination Adapt<TSource, TDestination>(this TSource source, TDestination destination, TypeAdapterConfig config)
101-
{
102-
var sourceType = source?.GetType();
103-
var destinationType = destination?.GetType();
104-
105-
if (sourceType == typeof(object)) // Infinity loop in ObjectAdapter if Runtime Type of source is Object
106-
return destination;
107-
108-
if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object))
109-
return UpdateFuncFromPackedinObject(source, destination, config, sourceType, destinationType);
110-
111-
var fn = config.GetMapToTargetFunction<TSource, TDestination>();
112-
return fn(source, destination);
113-
}
114-
115-
private static TDestination UpdateFuncFromPackedinObject<TSource, TDestination>(TSource source, TDestination destination, TypeAdapterConfig config, Type sourceType, Type destinationType)
116-
{
117-
dynamic del = config.GetMapToTargetFunction(sourceType, destinationType);
118-
119-
120-
if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible)
121-
{
122-
dynamic objfn = del;
123-
return objfn((dynamic)source, (dynamic)destination);
124-
}
125-
else
126-
{
127-
//NOTE: if type is non-public, we cannot use dynamic
128-
//DynamicInvoke is slow, but works with non-public
129-
return (TDestination)del.DynamicInvoke(source, destination);
130-
}
131-
}
132-
13378
/// <summary>
13479
/// Adapt the source object to the destination type.
13580
/// </summary>
@@ -170,45 +115,7 @@ private static TDestination UpdateFuncFromPackedinObject<TSource, TDestination>(
170115
//DynamicInvoke is slow, but works with non-public
171116
return del.DynamicInvoke(source);
172117
}
173-
}
174-
175-
/// <summary>
176-
/// Adapt the source object to an existing destination object.
177-
/// </summary>
178-
/// <param name="source">Source object to adapt.</param>
179-
/// <param name="destination">Destination object to populate.</param>
180-
/// <param name="sourceType">The type of the source object.</param>
181-
/// <param name="destinationType">The type of the destination object.</param>
182-
/// <returns>Adapted destination type.</returns>
183-
public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType)
184-
{
185-
return Adapt(source, destination, sourceType, destinationType, TypeAdapterConfig.GlobalSettings);
186-
}
187-
188-
/// <summary>
189-
/// Adapt the source object to an existing destination object.
190-
/// </summary>
191-
/// <param name="source">Source object to adapt.</param>
192-
/// <param name="destination">Destination object to populate.</param>
193-
/// <param name="sourceType">The type of the source object.</param>
194-
/// <param name="destinationType">The type of the destination object.</param>
195-
/// <param name="config">Configuration</param>
196-
/// <returns>Adapted destination type.</returns>
197-
public static object? Adapt(this object source, object destination, Type sourceType, Type destinationType, TypeAdapterConfig config)
198-
{
199-
var del = config.GetMapToTargetFunction(sourceType, destinationType);
200-
if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible)
201-
{
202-
dynamic fn = del;
203-
return fn((dynamic)source, (dynamic)destination);
204-
}
205-
else
206-
{
207-
//NOTE: if type is non-public, we cannot use dynamic
208-
//DynamicInvoke is slow, but works with non-public
209-
return del.DynamicInvoke(source, destination);
210-
}
211-
}
118+
}
212119

213120
/// <summary>
214121
/// Validate properties and Adapt the source object to the destination type.
Lines changed: 3 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,10 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Diagnostics.CodeAnalysis;
4-
using System.Linq;
52
using System.Reflection;
6-
using Mapster.Models;
73

84
namespace Mapster
95
{
10-
public static class TypeAdapter
6+
public static partial class TypeAdapter
117
{
12-
public static ITypeAdapterBuilder<TSource> BuildAdapter<TSource>(this TSource source)
13-
{
14-
return new TypeAdapterBuilder<TSource>(source, TypeAdapterConfig.GlobalSettings);
15-
}
16-
17-
public static ITypeAdapterBuilder<TSource> BuildAdapter<TSource>(this TSource source, TypeAdapterConfig config)
18-
{
19-
return new TypeAdapterBuilder<TSource>(source, config);
20-
}
21-
22-
/// <summary>
23-
/// Adapt the source object to the destination type.
24-
/// </summary>
25-
/// <typeparam name="TDestination">Destination type.</typeparam>
26-
/// <param name="source">Source object to adapt.</param>
27-
/// <returns>Adapted destination type.</returns>
28-
[return: NotNullIfNotNull(nameof(source))]
29-
public static TDestination? Adapt<TDestination>(this object? source)
30-
{
31-
return Adapt<TDestination>(source, TypeAdapterConfig.GlobalSettings);
32-
}
33-
34-
/// <summary>
35-
/// Adapt the source object to the destination type.
36-
/// </summary>
37-
/// <typeparam name="TDestination">Destination type.</typeparam>
38-
/// <param name="source">Source object to adapt.</param>
39-
/// <param name="config">Configuration</param>
40-
/// <returns>Adapted destination type.</returns>
41-
[return: NotNullIfNotNull(nameof(source))]
42-
public static TDestination? Adapt<TDestination>(this object? source, TypeAdapterConfig config)
43-
{
44-
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
45-
if (source == null)
46-
return default;
47-
var type = source.GetType();
48-
var fn = config.GetDynamicMapFunction<TDestination>(type);
49-
return fn(source)!;
50-
}
51-
52-
/// <summary>
53-
/// Adapt the source object to the destination type.
54-
/// </summary>
55-
/// <typeparam name="TSource">Source type.</typeparam>
56-
/// <typeparam name="TDestination">Destination type.</typeparam>
57-
/// <param name="source">Source object to adapt.</param>
58-
/// <returns>Adapted destination type.</returns>
59-
public static TDestination Adapt<TSource, TDestination>(this TSource source)
60-
{
61-
return TypeAdapter<TSource, TDestination>.Map(source);
62-
}
63-
64-
/// <summary>
65-
/// Adapt the source object to the destination type.
66-
/// </summary>
67-
/// <typeparam name="TSource">Source type.</typeparam>
68-
/// <typeparam name="TDestination">Destination type.</typeparam>
69-
/// <param name="source">Source object to adapt.</param>
70-
/// <param name="config">Configuration</param>
71-
/// <returns>Adapted destination type.</returns>
72-
public static TDestination Adapt<TSource, TDestination>(this TSource source, TypeAdapterConfig config)
73-
{
74-
var fn = config.GetMapFunction<TSource, TDestination>();
75-
return fn(source);
76-
}
77-
788
/// <summary>
799
/// Adapt the source object to the existing destination object.
8010
/// </summary>
@@ -105,9 +35,9 @@ public static TDestination Adapt<TSource, TDestination>(this TSource source, TDe
10535
if (sourceType == typeof(object)) // Infinity loop in ObjectAdapter if Runtime Type of source is Object
10636
return destination;
10737

108-
if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object))
38+
if (typeof(TSource) == typeof(object) || typeof(TDestination) == typeof(object))
10939
return UpdateFuncFromPackedinObject(source, destination, config, sourceType, destinationType);
110-
40+
11141
var fn = config.GetMapToTargetFunction<TSource, TDestination>();
11242
return fn(source, destination);
11343
}
@@ -130,48 +60,6 @@ private static TDestination UpdateFuncFromPackedinObject<TSource, TDestination>(
13060
}
13161
}
13262

133-
/// <summary>
134-
/// Adapt the source object to the destination type.
135-
/// </summary>
136-
/// <param name="source">Source object to adapt.</param>
137-
/// <param name="sourceType">The type of the source object.</param>
138-
/// <param name="destinationType">The type of the destination object.</param>
139-
/// <returns>Adapted destination type.</returns>
140-
public static object? Adapt(this object source, Type sourceType, Type destinationType)
141-
{
142-
if (source != null &&
143-
sourceType.IsOpenGenericType() && destinationType.IsOpenGenericType())
144-
{
145-
var arg = source.GetType().GetGenericArguments();
146-
return Adapt(source, sourceType.MakeGenericType(arg), destinationType.MakeGenericType(arg), TypeAdapterConfig.GlobalSettings);
147-
}
148-
return Adapt(source, sourceType, destinationType, TypeAdapterConfig.GlobalSettings);
149-
}
150-
151-
/// <summary>
152-
/// Adapt the source object to the destination type.
153-
/// </summary>
154-
/// <param name="source">Source object to adapt.</param>
155-
/// <param name="sourceType">The type of the source object.</param>
156-
/// <param name="destinationType">The type of the destination object.</param>
157-
/// <param name="config">Configuration</param>
158-
/// <returns>Adapted destination type.</returns>
159-
public static object? Adapt(this object source, Type sourceType, Type destinationType, TypeAdapterConfig config)
160-
{
161-
var del = config.GetMapFunction(sourceType, destinationType);
162-
if (sourceType.GetTypeInfo().IsVisible && destinationType.GetTypeInfo().IsVisible)
163-
{
164-
dynamic fn = del;
165-
return fn((dynamic)source);
166-
}
167-
else
168-
{
169-
//NOTE: if type is non-public, we cannot use dynamic
170-
//DynamicInvoke is slow, but works with non-public
171-
return del.DynamicInvoke(source);
172-
}
173-
}
174-
17563
/// <summary>
17664
/// Adapt the source object to an existing destination object.
17765
/// </summary>
@@ -209,101 +97,6 @@ private static TDestination UpdateFuncFromPackedinObject<TSource, TDestination>(
20997
return del.DynamicInvoke(source, destination);
21098
}
21199
}
212-
213-
/// <summary>
214-
/// Validate properties and Adapt the source object to the destination type.
215-
/// </summary>
216-
/// <typeparam name="TSource">Source type.</typeparam>
217-
/// <typeparam name="TDestination">Destination type.</typeparam>
218-
/// <param name="source">Source object to adapt.</param>
219-
/// <returns>Adapted destination type.</returns>
220-
public static TDestination ValidateAndAdapt<TSource, TDestination>(this TSource source)
221-
{
222-
var sourceType = typeof(TSource);
223-
var selectorType = typeof(TDestination);
224-
225-
var sourceProperties = new HashSet<string>(sourceType.GetProperties().Select(p => p.Name));
226-
var selectorProperties = new HashSet<string>(selectorType.GetProperties().Select(p=> p.Name));
227-
228-
foreach (var selectorProperty in selectorProperties)
229-
{
230-
if (sourceProperties.Contains(selectorProperty)) continue;
231-
throw new Exception($"Property {selectorProperty} does not exist in {sourceType.Name} and is not configured in Mapster");
232-
}
233-
return source.Adapt<TDestination>();
234-
}
235-
236-
/// <summary>
237-
/// Validate properties with configuration and Adapt the source object to the destination type.
238-
/// </summary>
239-
/// <typeparam name="TSource">Source type.</typeparam>
240-
/// <typeparam name="TDestination">Destination type.</typeparam>
241-
/// <param name="source">Source object to adapt.</param>
242-
/// <param name="config">Configuration</param>
243-
/// <returns>Adapted destination type.</returns>
244-
public static TDestination ValidateAndAdapt<TSource, TDestination>(this TSource source, TypeAdapterConfig config)
245-
{
246-
var sourceType = typeof(TSource);
247-
var selectorType = typeof(TDestination);
248-
249-
var sourceProperties = new HashSet<string>(sourceType.GetProperties().Select(p => p.Name));
250-
var selectorProperties = new HashSet<string>(selectorType.GetProperties().Select(p=> p.Name));
251-
252-
// Get the rule map for the current types
253-
var ruleMap = config.RuleMap;
254-
var typeTuple = new TypeTuple(sourceType, selectorType);
255-
ruleMap.TryGetValue(typeTuple, out var rule);
256-
257-
foreach (var selectorProperty in selectorProperties)
258-
{
259-
if (sourceProperties.Contains(selectorProperty)) continue;
260-
// Check whether the adapter config has a config for the property
261-
if (rule != null && rule.Settings.Resolvers.Any(r => r.DestinationMemberName.Equals(selectorProperty))) continue;
262-
throw new Exception($"Property {selectorProperty} does not exist in {sourceType.Name} and is not configured in Mapster");
263-
}
264-
return source.Adapt<TDestination>(config);
265-
}
266-
267100

268-
/// <summary>
269-
/// Adapt the source object to a destination type using a temporary configuration.
270-
/// A new TypeAdapterConfig is created for this call, ensuring GlobalSettings remain unchanged.
271-
/// Safe for init-only properties and record types.
272-
/// </summary>
273-
/// <typeparam name="TDestination">Destination type.</typeparam>
274-
/// <param name="source">Source object to adapt.</param>
275-
/// <param name="configAction">Action to customize the temporary config.</param>
276-
/// <returns>Adapted destination object of type TDestination.</returns>
277-
public static TDestination Adapt<TDestination>(this object? source, Action<TypeAdapterConfig> configAction)
278-
{
279-
var config = TypeAdapterConfig.GlobalSettings.Clone();
280-
configAction(config);
281-
return source.Adapt<TDestination>(config);
282-
}
283-
284-
/// <summary>
285-
/// Adapt the source object from TSource to TDestination using a dedicated TypeAdapterSetter.
286-
/// A temporary TypeAdapterConfig is created and configured via the setter.
287-
/// Safe for init-only properties and record types, without modifying GlobalSettings.
288-
/// </summary>
289-
/// <typeparam name="TSource">Source type.</typeparam>
290-
/// <typeparam name="TDestination">Destination type.</typeparam>
291-
/// <param name="source">Source object to adapt.</param>
292-
/// <param name="configAction">Action to customize the TypeAdapterSetter.</param>
293-
/// <returns>Adapted destination object of type TDestination.</returns>
294-
public static TDestination Adapt<TSource, TDestination>(this object? source, Action<TypeAdapterSetter<TSource, TDestination>> configAction)
295-
{
296-
var config = TypeAdapterConfig.GlobalSettings.Clone();
297-
var setter = config.ForType<TSource, TDestination>();
298-
configAction(setter);
299-
setter.Settings.Resolvers.Reverse();
300-
return source.Adapt<TDestination>(config);
301-
}
302-
}
303-
304-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "<Pending>")]
305-
public static class TypeAdapter<TSource, TDestination>
306-
{
307-
public static Func<TSource, TDestination> Map = TypeAdapterConfig.GlobalSettings.GetMapFunction<TSource, TDestination>();
308101
}
309102
}

0 commit comments

Comments
 (0)