|
1 | 1 | # ValueMapper |
2 | 2 |
|
3 | | -ValueMapper is a straightforward, easy-to-use object-to-object mapping utility for .NET. It provides a convenient way to map properties between different object types with minimal configuration. |
| 3 | +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. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- ✨ Zero dependencies |
| 8 | +- 🚀 High performance |
| 9 | +- 💡 Simple API |
| 10 | +- 🔄 Automatic type conversion |
| 11 | +- 🏷️ Custom property mapping via attributes |
| 12 | +- ⏭️ Property ignoring |
| 13 | +- 📝 Collection mapping |
| 14 | +- 🔄 Enum mapping (case-insensitive) |
| 15 | +- 🧵 Parallel collection mapping for large datasets |
| 16 | +- 🔒 Thread-safe operation |
| 17 | +- 🔥 Mapping compilation caching |
4 | 18 |
|
5 | 19 | ## Installation |
6 | 20 |
|
7 | 21 | ```shell |
8 | 22 | dotnet add package ValueMapper |
9 | 23 | ``` |
10 | 24 |
|
11 | | -## Quick Start |
| 25 | +## Usage Examples |
| 26 | + |
| 27 | +### Basic Property Mapping |
12 | 28 |
|
13 | 29 | ```csharp |
14 | | -using ValueMapperUtility; |
| 30 | +var source = new Source |
| 31 | +{ |
| 32 | + Name = "John Doe", |
| 33 | + Age = 30, |
| 34 | + City = "New York" |
| 35 | +}; |
| 36 | + |
| 37 | +var destination = ValueMapper.Map<Source, Destination>(source); |
| 38 | +``` |
15 | 39 |
|
16 | | -// Define your classes |
17 | | -public class UserDto |
| 40 | +### Custom Property Mapping Using Attributes |
| 41 | + |
| 42 | +```csharp |
| 43 | +public class Source |
18 | 44 | { |
19 | | - public string Name { get; set; } |
20 | | - public int Age { get; set; } |
| 45 | + [ValueMapperMapping("CustomName")] |
| 46 | + public string SourceProperty { get; set; } |
21 | 47 | } |
22 | 48 |
|
23 | | -public class UserEntity |
| 49 | +public class Destination |
24 | 50 | { |
25 | | - public string Name { get; set; } |
26 | | - public int Age { get; set; } |
| 51 | + public string CustomName { get; set; } |
27 | 52 | } |
28 | 53 |
|
29 | | -// Perform mapping |
30 | | -var dto = new UserDto { Name = "John Doe", Age = 30 }; |
31 | | -var entity = ValueMapper.Map<UserDto, UserEntity>(dto); |
| 54 | +var source = new Source { SourceProperty = "Custom Value" }; |
| 55 | +var destination = ValueMapper.Map<Source, Destination>(source); |
| 56 | +// destination.CustomName will contain "Custom Value" |
32 | 57 | ``` |
33 | 58 |
|
34 | | -## Features |
35 | | - |
36 | | -- Simple property matching by name |
37 | | -- Basic type conversion support |
38 | | -- Custom property mapping using attributes |
39 | | -- Property exclusion support |
40 | | -- Collection mapping |
41 | | -- Enum mapping support |
| 59 | +### Ignoring Properties |
42 | 60 |
|
43 | | -## Documentation |
| 61 | +```csharp |
| 62 | +public class Source |
| 63 | +{ |
| 64 | + public string Name { get; set; } |
| 65 | + [ValueMapperIgnore] |
| 66 | + public string IgnoredProperty { get; set; } |
| 67 | +} |
44 | 68 |
|
45 | | -For full documentation, visit our [GitHub repository](https://github.com/TechFusionMasters/ValueMapper). |
| 69 | +// Or ignore properties at runtime |
| 70 | +var ignoredProperties = new HashSet<string> { "Age" }; |
| 71 | +var destination = ValueMapper.Map<Source, Destination>(source, ignoredProperties); |
| 72 | +``` |
46 | 73 |
|
47 | 74 | ### Collection Mapping |
48 | 75 |
|
49 | | -ValueMapper provides support for collections in two ways: |
50 | | - |
51 | | -1. Mapping Lists of Objects using `MapList`: |
52 | | - |
53 | 76 | ```csharp |
54 | | -var dtoList = new List<UserDto> |
| 77 | +var sourceList = new List<Source> |
55 | 78 | { |
56 | | - new UserDto { Name = "John Doe", Age = 30 }, |
57 | | - new UserDto { Name = "Jane Doe", Age = 28 } |
| 79 | + new Source { Name = "John", Age = 30 }, |
| 80 | + new Source { Name = "Jane", Age = 25 } |
58 | 81 | }; |
59 | 82 |
|
60 | | -// Maps each object in the list, with automatic parallelization for large lists |
61 | | -var entityList = ValueMapper.MapList<UserDto, UserEntity>(dtoList); |
| 83 | +var destinationList = ValueMapper.MapList<Source, Destination>(sourceList); |
62 | 84 | ``` |
63 | 85 |
|
64 | | -2. Mapping Collection Properties: |
| 86 | +### Enum Mapping (Case-Insensitive) |
65 | 87 |
|
66 | 88 | ```csharp |
67 | | -public class UserDto |
| 89 | +public enum SampleEnum |
68 | 90 | { |
69 | | - public string Name { get; set; } |
70 | | - public List<string> Roles { get; set; } |
| 91 | + None, |
| 92 | + Value1, |
| 93 | + Value2 |
71 | 94 | } |
72 | 95 |
|
73 | | -public class UserEntity |
| 96 | +public class Source |
74 | 97 | { |
75 | | - public string Name { get; set; } |
76 | | - public List<string> Roles { get; set; } |
| 98 | + public string EnumValue { get; set; } // Can be "Value1" or "value1" |
77 | 99 | } |
78 | 100 |
|
79 | | -// Both Name and Roles will be mapped automatically |
80 | | -var dto = new UserDto |
| 101 | +public class Destination |
81 | 102 | { |
82 | | - Name = "John", |
83 | | - Roles = new List<string> { "Admin", "User" } |
84 | | -}; |
85 | | - |
86 | | -var entity = ValueMapper.Map<UserDto, UserEntity>(dto); |
| 103 | + public SampleEnum EnumValue { get; set; } |
| 104 | +} |
87 | 105 | ``` |
88 | 106 |
|
89 | | -### Custom Property Mapping |
90 | | - |
91 | | -Use the `ValueMapperMappingAttribute` to map properties with different names: |
| 107 | +### Type Conversion Support |
92 | 108 |
|
93 | 109 | ```csharp |
94 | 110 | public class Source |
95 | 111 | { |
96 | | - public string FullName { get; set; } |
| 112 | + public int IntValue { get; set; } |
| 113 | + public double DoubleValue { get; set; } |
| 114 | + public string StringNumber { get; set; } |
97 | 115 | } |
98 | 116 |
|
99 | 117 | public class Destination |
100 | 118 | { |
101 | | - [ValueMapperMapping("FullName")] |
102 | | - public string Name { get; set; } |
| 119 | + public long LongValue { get; set; } // Converts from int |
| 120 | + public float FloatValue { get; set; } // Converts from double |
| 121 | + public int IntFromString { get; set; } // Converts from string |
103 | 122 | } |
104 | 123 | ``` |
105 | 124 |
|
106 | | -### Ignoring Properties |
107 | | - |
108 | | -Use the `ValueMapperIgnoreAttribute` to exclude properties from mapping: |
| 125 | +### Nullable Handling |
109 | 126 |
|
110 | 127 | ```csharp |
111 | | -public class UserEntity |
| 128 | +public class Source |
112 | 129 | { |
113 | | - public string Name { get; set; } |
| 130 | + public string Value { get; set; } // Can be null |
| 131 | +} |
114 | 132 |
|
115 | | - [ValueMapperIgnore] |
116 | | - public string InternalId { get; set; } |
| 133 | +public class Destination |
| 134 | +{ |
| 135 | + public int? NullableValue { get; set; } // Will be null if source is null |
117 | 136 | } |
118 | 137 | ``` |
119 | 138 |
|
120 | | -### Type Conversion Support |
| 139 | +## Performance |
| 140 | + |
| 141 | +ValueMapper is designed for high performance. Here are some benchmark results comparing it with other popular mappers: |
| 142 | + |
| 143 | +- Single object mapping |
| 144 | +- Collection mapping (100,000 items) |
| 145 | +- Parallel collection mapping |
| 146 | +- Cold start vs. Cached performance |
| 147 | + |
| 148 | +Run the benchmarks yourself: |
| 149 | + |
| 150 | +```shell |
| 151 | +cd ValueMapper/Benchmark |
| 152 | +dotnet run # Full benchmarks |
| 153 | +dotnet run quick # Quick benchmarks |
| 154 | +``` |
| 155 | + |
| 156 | +## Cache Management |
| 157 | + |
| 158 | +```csharp |
| 159 | +// Clear all caches |
| 160 | +ValueMapper.ClearCaches(); |
| 161 | + |
| 162 | +// Pre-warm mapping for specific types |
| 163 | +ValueMapper.PreWarmMapping<Source, Destination>(); |
| 164 | + |
| 165 | +// Clear cache for specific types |
| 166 | +ValueMapper.Clear<Source, Destination>(); |
| 167 | +``` |
121 | 168 |
|
122 | | -ValueMapper handles various type conversions: |
| 169 | +## Known Limitations |
123 | 170 |
|
124 | | -- Numeric type conversions (int, long, double, decimal, etc.) |
125 | | -- String to/from numeric types |
126 | | -- String to/from enum types (with case-insensitive parsing) |
127 | | -- Enum to/from numeric types |
128 | | -- Nullable type handling |
129 | | -- Custom type conversions through the Convert.ChangeType method |
| 171 | +1. Deep object mapping is not currently supported |
130 | 172 |
|
131 | | -## Limitations |
| 173 | + - The `Map_DeepObjectMapping_ShouldMapCorrectly` test demonstrates this limitation |
| 174 | + - Complex nested objects with multiple levels are not automatically mapped |
132 | 175 |
|
133 | | -- Does not support deep object mapping (nested objects must be mapped separately) |
134 | | -- Only public properties are mapped |
135 | | -- Properties must have both getter and setter to be mapped |
136 | | -- Basic caching implementation |
137 | | -- Not optimized for high-performance scenarios |
| 176 | +2. No circular reference detection |
| 177 | +3. No support for mapping private properties |
| 178 | +4. Collection type conversion (e.g., List<T> to Array<T>) is not supported |
| 179 | +5. No support for custom value converters |
| 180 | +6. No support for conditional mapping |
138 | 181 |
|
139 | 182 | ## Contributing |
140 | 183 |
|
|
0 commit comments