Skip to content

Commit 50092c1

Browse files
committed
added unit test and updated readme.md
1 parent 379abb7 commit 50092c1

File tree

5 files changed

+556
-34
lines changed

5 files changed

+556
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616
/ValueMapper/ValueMapperCore/bin
1717
/ValueMapper/ValueMapperCore/obj
1818
/ValueMapper/.vs
19+
/ValueMapper/Benchmark/BenchmarkDotNet.Artifacts

README.md

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,14 @@
22

33
A high-performance, lightweight object-to-object mapper for .NET with zero dependencies. ValueMapper provides fast mapping capabilities with a simple API, making it easy to map between different object types while maintaining good performance.
44

5-
## Features
6-
7-
- ⚙️ Zero configuration required
8-
- ✨ Zero dependencies
9-
- 🚀 High performance
10-
- 💡 Simple API
11-
- 🔄 Automatic type conversion
12-
- 🏷️ Custom property mapping via attributes
13-
- ⏭️ Property ignoring
14-
- 📝 Collection mapping
15-
- 🔄 Enum mapping (case-insensitive)
16-
- 🧵 Parallel collection mapping for large datasets
17-
- 🔒 Thread-safe operation
18-
- 🔥 Mapping compilation caching
19-
205
## Feature Comparison
216

227
| Feature | ValueMapper | Mapster | AutoMapper |
238
| ---------------------------- | ------------------- | ------------- | -------------- |
249
| Zero Dependencies ||||
2510
| Basic Property Mapping ||||
2611
| Flattening ||||
27-
| Deep Object Mapping | |||
12+
| Deep Object Mapping | |||
2813
| Collection Mapping ||||
2914
| Enum Mapping ||||
3015
| Custom Property Mapping | ✅ (attr) |||
@@ -46,7 +31,23 @@ A high-performance, lightweight object-to-object mapper for .NET with zero depen
4631

4732
\* Based on benchmark results for single object mapping. For collection mapping (100,000 items), ValueMapper performs better: ValueMapper (39.84ms), Mapster (65.34ms), AutoMapper (70.80ms).
4833

49-
## Installation - [nuget](https://www.nuget.org/packages/ValueMapper)
34+
- Can be implemented manually
35+
36+
## Features
37+
38+
- ✨ Zero dependencies
39+
- 🚀 High performance
40+
- 💡 Simple API
41+
- 🔄 Automatic type conversion
42+
- 🏷️ Custom property mapping via attributes
43+
- ⏭️ Property ignoring
44+
- 📝 Collection mapping
45+
- 🔄 Enum mapping (case-insensitive)
46+
- 🧵 Parallel collection mapping for large datasets
47+
- 🔒 Thread-safe operation
48+
- 🔥 Mapping compilation caching
49+
50+
## Installation
5051

5152
```shell
5253
dotnet add package ValueMapper
@@ -166,6 +167,75 @@ public class Destination
166167
}
167168
```
168169

170+
### Deep Object Mapping
171+
172+
ValueMapper supports mapping nested objects with multiple levels of depth, including collections and dictionaries:
173+
174+
```csharp
175+
public class DeepSourceObject
176+
{
177+
public int Id { get; set; }
178+
public string Name { get; set; }
179+
public DeepSourceChild Child { get; set; }
180+
}
181+
182+
public class DeepSourceChild
183+
{
184+
public int ChildId { get; set; }
185+
public string Description { get; set; }
186+
public Dictionary<string, string> Metadata { get; set; }
187+
public List<string> Tags { get; set; }
188+
public DeepSourceGrandChild GrandChild { get; set; }
189+
}
190+
191+
public class DeepSourceGrandChild
192+
{
193+
public int GrandChildId { get; set; }
194+
public bool IsActive { get; set; }
195+
public DateTime CreatedDate { get; set; }
196+
}
197+
198+
// Destination classes with matching structure
199+
public class DeepDestinationObject
200+
{
201+
public int Id { get; set; }
202+
public string Name { get; set; }
203+
public DeepDestinationChild Child { get; set; }
204+
}
205+
206+
// ... similar structure for DeepDestinationChild and DeepDestinationGrandChild
207+
208+
var source = new DeepSourceObject
209+
{
210+
Id = 1,
211+
Name = "Root Object",
212+
Child = new DeepSourceChild
213+
{
214+
ChildId = 100,
215+
Description = "Child Object",
216+
Metadata = new Dictionary<string, string> { { "key1", "value1" } },
217+
Tags = new List<string> { "tag1", "tag2" },
218+
GrandChild = new DeepSourceGrandChild
219+
{
220+
GrandChildId = 1000,
221+
IsActive = true,
222+
CreatedDate = new DateTime(2024, 1, 1)
223+
}
224+
}
225+
};
226+
227+
var destination = ValueMapper.Map<DeepSourceObject, DeepDestinationObject>(source);
228+
// All nested objects are automatically mapped
229+
```
230+
231+
**Collection Mapping Behavior:**
232+
- **Lists**: Creates new List instances (shallow copy - same objects, new container)
233+
- Null sources become empty lists `[]`
234+
- **Dictionaries**: Copies references (same instance)
235+
- Null sources remain null
236+
- **Complex Objects**: Deep mapping with new instances
237+
- **Primitive Types**: Direct value copying
238+
169239
## Performance
170240

171241
ValueMapper is designed for high performance. Here are some benchmark results comparing it with other popular mappers:
@@ -243,16 +313,11 @@ ValueMapper.Clear<Source, Destination>();
243313

244314
## Known Limitations
245315

246-
1. Deep object mapping is not currently supported
247-
248-
- The `Map_DeepObjectMapping_ShouldMapCorrectly` test demonstrates this limitation
249-
- Complex nested objects with multiple levels are not automatically mapped
250-
251-
2. No circular reference detection
252-
3. No support for mapping private properties
253-
4. Collection type conversion (e.g., List<T> to Array<T>) is not supported
254-
5. No support for custom value converters
255-
6. No support for conditional mapping
316+
1. No circular reference detection
317+
2. No support for mapping private properties
318+
3. Collection type conversion (e.g., List<T> to Array<T>) is not supported
319+
4. No support for custom value converters
320+
5. No support for conditional mapping
256321

257322
## Contributing
258323

ValueMapper/UnitTestXUnitNet6/TestModels.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,83 @@ public class FlatDestinationObject
149149
public bool GrandChildIsActive { get; set; }
150150
public DateTime GrandChildCreatedDate { get; set; }
151151
}
152+
153+
// Models for testing complex collections in deep object mapping
154+
public class ComplexMetadataItem
155+
{
156+
public int Id { get; set; }
157+
public string Value { get; set; }
158+
}
159+
160+
public class ComplexTag
161+
{
162+
public int Id { get; set; }
163+
public string Name { get; set; }
164+
public bool IsActive { get; set; }
165+
}
166+
167+
public class DeepSourceObjectWithComplexCollections
168+
{
169+
public int Id { get; set; }
170+
public string Name { get; set; }
171+
public DeepSourceChildWithComplexCollections Child { get; set; }
172+
}
173+
174+
public class DeepSourceChildWithComplexCollections
175+
{
176+
public int ChildId { get; set; }
177+
public string Description { get; set; }
178+
public Dictionary<string, ComplexMetadataItem> ComplexMetadata { get; set; }
179+
public List<ComplexTag> ComplexTags { get; set; }
180+
public DeepSourceGrandChild GrandChild { get; set; }
181+
}
182+
183+
public class DeepDestinationObjectWithComplexCollections
184+
{
185+
public int Id { get; set; }
186+
public string Name { get; set; }
187+
public DeepDestinationChildWithComplexCollections Child { get; set; }
188+
}
189+
190+
public class DeepDestinationChildWithComplexCollections
191+
{
192+
public int ChildId { get; set; }
193+
public string Description { get; set; }
194+
public Dictionary<string, ComplexMetadataItem> ComplexMetadata { get; set; }
195+
public List<ComplexTag> ComplexTags { get; set; }
196+
public DeepDestinationGrandChild GrandChild { get; set; }
197+
}
198+
199+
// Models for testing nested collections in deep object mapping
200+
public class DeepSourceObjectWithNestedCollections
201+
{
202+
public int Id { get; set; }
203+
public string Name { get; set; }
204+
public DeepSourceChildWithNestedCollections Child { get; set; }
205+
}
206+
207+
public class DeepSourceChildWithNestedCollections
208+
{
209+
public int ChildId { get; set; }
210+
public string Description { get; set; }
211+
public Dictionary<string, List<string>> NestedMetadata { get; set; }
212+
public List<List<string>> NestedTags { get; set; }
213+
public DeepSourceGrandChild GrandChild { get; set; }
214+
}
215+
216+
public class DeepDestinationObjectWithNestedCollections
217+
{
218+
public int Id { get; set; }
219+
public string Name { get; set; }
220+
public DeepDestinationChildWithNestedCollections Child { get; set; }
221+
}
222+
223+
public class DeepDestinationChildWithNestedCollections
224+
{
225+
public int ChildId { get; set; }
226+
public string Description { get; set; }
227+
public Dictionary<string, List<string>> NestedMetadata { get; set; }
228+
public List<List<string>> NestedTags { get; set; }
229+
public DeepDestinationGrandChild GrandChild { get; set; }
230+
}
152231
}

0 commit comments

Comments
 (0)