Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 5d98d20

Browse files
bnayaemythz
authored andcommitted
optional mapping for ToObjectDictionary (#525)
* optional mapping for ToObjectDictionary * log htm * overload instead of optional parameter for better support for JS.Configure() * test
1 parent 5654a94 commit 5d98d20

File tree

4 files changed

+120
-26
lines changed

4 files changed

+120
-26
lines changed

src/ServiceStack.Text/PlatformExtensions.cs

Lines changed: 104 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -658,32 +658,74 @@ public void SetValue(object instance, object value)
658658
}
659659
}
660660

661+
private static Dictionary<string, object> ConvertToDictionary<T>(
662+
IEnumerable<KeyValuePair<string, T>> collection,
663+
Func<string, object, object> mapper = null)
664+
{
665+
if (mapper != null)
666+
{
667+
return mapper.MapToDictionary(collection);
668+
}
669+
670+
var to = new Dictionary<string, object>();
671+
foreach (var entry in collection)
672+
{
673+
string key = entry.Key;
674+
object value = entry.Value;
675+
to[key] = value;
676+
}
677+
return to;
678+
}
679+
680+
private static Dictionary<string, object> MapToDictionary<T>(
681+
this Func<string, object, object> mapper,
682+
IEnumerable<KeyValuePair<string, T>> collection)
683+
{
684+
return collection.ToDictionary(
685+
pair => pair.Key,
686+
pair => mapper(pair.Key, pair.Value));
687+
}
688+
661689
public static Dictionary<string, object> ToObjectDictionary(this object obj)
690+
{
691+
return ToObjectDictionary(obj, null);
692+
}
693+
694+
public static Dictionary<string, object> ToObjectDictionary(
695+
this object obj,
696+
Func<string, object, object> mapper)
662697
{
663698
if (obj == null)
664699
return null;
665700

666701
if (obj is Dictionary<string, object> alreadyDict)
702+
{
703+
if (mapper != null)
704+
return mapper.MapToDictionary(alreadyDict);
667705
return alreadyDict;
706+
}
668707

669708
if (obj is IDictionary<string, object> interfaceDict)
709+
{
710+
if (mapper != null)
711+
return mapper.MapToDictionary(interfaceDict);
670712
return new Dictionary<string, object>(interfaceDict);
713+
}
671714

672715
var to = new Dictionary<string, object>();
673716
if (obj is Dictionary<string, string> stringDict)
674717
{
675-
foreach (var entry in stringDict)
676-
{
677-
to[entry.Key] = entry.Value;
678-
}
679-
return to;
718+
return ConvertToDictionary(stringDict, mapper);
680719
}
681720

682721
if (obj is IDictionary d)
683722
{
684723
foreach (var key in d.Keys)
685724
{
686-
to[key.ToString()] = d[key];
725+
string k = key.ToString();
726+
object v = d[key];
727+
v = mapper?.Invoke(k, v) ?? v;
728+
to[k] = v;
687729
}
688730
return to;
689731
}
@@ -692,26 +734,21 @@ public static Dictionary<string, object> ToObjectDictionary(this object obj)
692734
{
693735
for (var i = 0; i < nvc.Count; i++)
694736
{
695-
to[nvc.GetKey(i)] = nvc.Get(i);
737+
string k = nvc.GetKey(i);
738+
object v = nvc.Get(i);
739+
v = mapper?.Invoke(k, v) ?? v;
740+
to[k] = v;
696741
}
697742
return to;
698743
}
699744

700745
if (obj is IEnumerable<KeyValuePair<string, object>> objKvps)
701746
{
702-
foreach (var kvp in objKvps)
703-
{
704-
to[kvp.Key] = kvp.Value;
705-
}
706-
return to;
747+
return ConvertToDictionary(objKvps, mapper);
707748
}
708749
if (obj is IEnumerable<KeyValuePair<string, string>> strKvps)
709750
{
710-
foreach (var kvp in strKvps)
711-
{
712-
to[kvp.Key] = kvp.Value;
713-
}
714-
return to;
751+
return ConvertToDictionary(strKvps, mapper);
715752
}
716753

717754
var type = obj.GetType();
@@ -724,22 +761,60 @@ public static Dictionary<string, object> ToObjectDictionary(this object obj)
724761
{
725762
var key = keyGetter(entry);
726763
var value = valueGetter(entry);
727-
to[key.ConvertTo<string>()] = value;
764+
string k = key.ConvertTo<string>();
765+
value = mapper?.Invoke(k, value) ?? value;
766+
to[k] = value;
728767
}
729768
return to;
730769
}
731-
770+
732771

733772
if (obj is KeyValuePair<string, object> objKvp)
734-
return new Dictionary<string, object> { { nameof(objKvp.Key), objKvp.Key }, { nameof(objKvp.Value), objKvp.Value } };
773+
{
774+
string kk = nameof(objKvp.Key);
775+
object kv = objKvp.Key;
776+
kv = mapper?.Invoke(kk, kv) ?? kv;
777+
778+
string vk = nameof(objKvp.Value);
779+
object vv = objKvp.Value;
780+
vv = mapper?.Invoke(vk, vv) ?? vv;
781+
782+
return new Dictionary<string, object>
783+
{
784+
[kk] = kv,
785+
[vk] = vv
786+
};
787+
}
735788
if (obj is KeyValuePair<string, string> strKvp)
736-
return new Dictionary<string, object> { { nameof(strKvp.Key), strKvp.Key }, { nameof(strKvp.Value), strKvp.Value } };
737-
789+
{
790+
string kk = nameof(objKvp.Key);
791+
object kv = strKvp.Key;
792+
kv = mapper?.Invoke(kk, kv) ?? kv;
793+
794+
string vk = nameof(strKvp.Value);
795+
object vv = strKvp.Value;
796+
vv = mapper?.Invoke(vk, vv) ?? vv;
797+
798+
return new Dictionary<string, object>
799+
{
800+
[kk] = kv,
801+
[vk] = vv
802+
};
803+
}
738804
if (type.GetKeyValuePairTypes(out _, out var _))
739805
{
740-
return new Dictionary<string, object> {
741-
{ "Key", TypeProperties.Get(type).GetPublicGetter("Key")(obj).ConvertTo<string>() },
742-
{ "Value", TypeProperties.Get(type).GetPublicGetter("Value")(obj) },
806+
string kk = "Key";
807+
object kv = TypeProperties.Get(type).GetPublicGetter("Key")(obj).ConvertTo<string>();
808+
kv = mapper?.Invoke(kk, kv) ?? kv;
809+
810+
string vk = "Value";
811+
object vv = TypeProperties.Get(type).GetPublicGetter("Value")(obj);
812+
vv = mapper?.Invoke(vk, vv) ?? vv;
813+
814+
return new Dictionary<string, object>
815+
{
816+
[kk] = kv,
817+
[vk] = vv
743818
};
744819
}
745820

@@ -748,7 +823,10 @@ public static Dictionary<string, object> ToObjectDictionary(this object obj)
748823

749824
foreach (var fieldDef in def.Fields)
750825
{
751-
to[fieldDef.Name] = fieldDef.GetValueFn(obj);
826+
string k = fieldDef.Name;
827+
object v = fieldDef.GetValueFn(obj);
828+
v = mapper?.Invoke(k, v) ?? v;
829+
to[k] = v;
752830
}
753831

754832
return to;

src/UpgradeLog.htm

41.6 KB
Binary file not shown.

tests/ServiceStack.Text.Tests/AutoMappingObjectDictionaryTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ namespace ServiceStack.Text.Tests
1111
[TestFixture]
1212
public class AutoMappingObjectDictionaryTests
1313
{
14+
[Test]
15+
public void Can_convert_Car_to_ObjectDictionary_WithMapper()
16+
{
17+
var dto = new DtoWithEnum { Name = "Dan", Color = Color.Blue};
18+
var map = dto.ToObjectDictionary((k,v) => k == nameof(Color) ? v.ToString().ToLower() : v);
19+
20+
Assert.That(map["Color"], Is.EqualTo(Color.Blue.ToString().ToLower()));
21+
Assert.That(map["Name"], Is.EqualTo(dto.Name));
22+
}
23+
1424
[Test]
1525
public void Can_convert_Car_to_ObjectDictionary()
1626
{

tests/ServiceStack.Text.Tests/AutoMappingTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ public class NullableConversionDto
131131
public decimal? Amount { get; set; }
132132
}
133133

134+
public class DtoWithEnum
135+
{
136+
public string Name { get; set; }
137+
public Color Color { get; set; }
138+
}
139+
134140
public class NullableEnumConversion
135141
{
136142
public Color Color { get; set; }

0 commit comments

Comments
 (0)