Skip to content

Commit 1a2a913

Browse files
committed
1) Adding support for excluding [NonSerialized] members from serialization, this is prerequisite for dotnet#2.
2) Adding support for ReadOnlyDictionary.
1 parent e38e54f commit 1a2a913

File tree

4 files changed

+66
-36
lines changed

4 files changed

+66
-36
lines changed

src/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
33
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
44
<PropertyGroup>
@@ -158,4 +158,4 @@
158158
<None Include="project.json" />
159159
</ItemGroup>
160160
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
161-
</Project>
161+
</Project>

src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -439,47 +439,50 @@ static internal bool IsNonAttributedTypeValidForSerialization(Type type)
439439
}
440440
}
441441

442-
private static string[] s_knownSerializableTypeNames = new string[] {
443-
"System.Collections.Queue",
444-
"System.Collections.Stack",
445-
"System.Globalization.CultureInfo",
446-
"System.Version",
447-
"System.Collections.Generic.KeyValuePair`2",
448-
"System.Collections.Generic.Queue`1",
449-
"System.Collections.Generic.Stack`1",
450-
"System.Collections.ObjectModel.ReadOnlyCollection`1",
451-
"System.Collections.ObjectModel.ReadOnlyDictionary`2",
452-
"System.Tuple`1",
453-
"System.Tuple`2",
454-
"System.Tuple`3",
455-
"System.Tuple`4",
456-
"System.Tuple`5",
457-
"System.Tuple`6",
458-
"System.Tuple`7",
459-
"System.Tuple`8",
442+
private static readonly Dictionary<string, string[]> s_knownSerializableTypeInfos = new Dictionary<string, string[]> {
443+
{ "System.Collections.Generic.KeyValuePair`2", Array.Empty<string>() },
444+
{ "System.Collections.Generic.Queue`1", new [] { "_syncRoot" } },
445+
{ "System.Collections.Generic.Stack`1", new [] {"_syncRoot" } },
446+
{ "System.Collections.ObjectModel.ReadOnlyCollection`1", new [] {"_syncRoot" } },
447+
{ "System.Collections.ObjectModel.ReadOnlyDictionary`2", new [] {"_syncRoot", "_keys","_values" } },
448+
{ "System.Tuple`1", Array.Empty<string>() },
449+
{ "System.Tuple`2", Array.Empty<string>() },
450+
{ "System.Tuple`3", Array.Empty<string>() },
451+
{ "System.Tuple`4", Array.Empty<string>() },
452+
{ "System.Tuple`5", Array.Empty<string>() },
453+
{ "System.Tuple`6", Array.Empty<string>() },
454+
{ "System.Tuple`7", Array.Empty<string>() },
455+
{ "System.Tuple`8", Array.Empty<string>() },
456+
{ "System.Collections.Queue", new [] {"_syncRoot" } },
457+
{ "System.Collections.Stack", new [] {"_syncRoot" } },
458+
{ "System.Globalization.CultureInfo", Array.Empty<string>() },
459+
{ "System.Version", Array.Empty<string>() },
460460
};
461461

462+
private static string GetGeneralTypeName(Type type)
463+
{
464+
TypeInfo typeInfo = type.GetTypeInfo();
465+
return type.GetTypeInfo().IsGenericType && !typeInfo.IsGenericParameter
466+
? typeInfo.GetGenericTypeDefinition().FullName
467+
: type.FullName;
468+
}
469+
462470
internal static bool IsKnownSerializableType(Type type)
463471
{
464472
// Applies to known types that DCS understands how to serialize/deserialize
465473
//
474+
string typeFullName = GetGeneralTypeName(type);
466475

467-
// Ajdust for generic type
468-
if (type.GetTypeInfo().IsGenericType && !type.GetTypeInfo().IsGenericTypeDefinition)
469-
{
470-
type = type.GetGenericTypeDefinition();
471-
}
476+
return s_knownSerializableTypeInfos.ContainsKey(typeFullName)
477+
|| Globals.TypeOfException.IsAssignableFrom(type);
478+
}
472479

473-
// Check for known types
474-
if (Enumerable.Contains(s_knownSerializableTypeNames, type.FullName))
475-
{
476-
return true;
477-
}
478-
//Enable ClassDataContract to give support to Exceptions.
479-
if (Globals.TypeOfException.IsAssignableFrom(type))
480-
return true;
480+
internal static bool IsNonSerializedMember(Type type, string memberName)
481+
{
482+
string typeFullName = GetGeneralTypeName(type);
481483

482-
return false;
484+
return s_knownSerializableTypeInfos.ContainsKey(typeFullName)
485+
&& s_knownSerializableTypeInfos[typeFullName].Contains(memberName);
483486
}
484487

485488
private XmlDictionaryString[] CreateChildElementNamespaces()
@@ -1073,8 +1076,7 @@ private void ImportDataMembers()
10731076

10741077
private static bool CanSerializeMember(FieldInfo field)
10751078
{
1076-
return field != null &&
1077-
field.FieldType != Globals.TypeOfObject; // Don't really know how to serialize plain System.Object instance;
1079+
return field != null && !ClassDataContract.IsNonSerializedMember(field.DeclaringType, field.Name);
10781080
}
10791081

10801082
private bool SetIfGetOnlyCollection(DataMember memberContract)

src/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,20 @@ public static void DCJS_ReadOnlyCollection()
15961596
Assert.StrictEqual(value[1], deserializedValue[1]);
15971597
}
15981598

1599+
[Fact]
1600+
public static void DCJS_ReadOnlyDictionary()
1601+
{
1602+
var dict = new Dictionary<string, int>();
1603+
dict["Foo"] = 1;
1604+
dict["Bar"] = 2;
1605+
ReadOnlyDictionary<string, int> value = new ReadOnlyDictionary<string, int>(dict);
1606+
var deserializedValue = SerializeAndDeserialize(value, @"{""_dictionary"":[{""Key"":""Foo"",""Value"":1},{""Key"":""Bar"",""Value"":2}]}");
1607+
1608+
Assert.StrictEqual(value.Count, deserializedValue.Count);
1609+
Assert.StrictEqual(value["Foo"], deserializedValue["Foo"]);
1610+
Assert.StrictEqual(value["Bar"], deserializedValue["Bar"]);
1611+
}
1612+
15991613
[Fact]
16001614
public static void DCJS_KeyValuePair()
16011615
{

src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,20 @@ public static void DCS_ReadOnlyCollection()
17401740
Assert.StrictEqual(value[1], deserializedValue[1]);
17411741
}
17421742

1743+
[Fact]
1744+
public static void DCS_ReadOnlyDictionary()
1745+
{
1746+
var dict = new Dictionary<string, int>();
1747+
dict["Foo"] = 1;
1748+
dict["Bar"] = 2;
1749+
ReadOnlyDictionary<string, int> value = new ReadOnlyDictionary<string, int>(dict);
1750+
var deserializedValue = SerializeAndDeserialize(value, @"<ReadOnlyDictionaryOfstringint xmlns=""http://schemas.datacontract.org/2004/07/System.Collections.ObjectModel"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><_dictionary xmlns:a=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""><a:KeyValueOfstringint><a:Key>Foo</a:Key><a:Value>1</a:Value></a:KeyValueOfstringint><a:KeyValueOfstringint><a:Key>Bar</a:Key><a:Value>2</a:Value></a:KeyValueOfstringint></_dictionary></ReadOnlyDictionaryOfstringint>");
1751+
1752+
Assert.StrictEqual(value.Count, deserializedValue.Count);
1753+
Assert.StrictEqual(value["Foo"], deserializedValue["Foo"]);
1754+
Assert.StrictEqual(value["Bar"], deserializedValue["Bar"]);
1755+
}
1756+
17431757
[Fact]
17441758
public static void DCS_KeyValuePair()
17451759
{

0 commit comments

Comments
 (0)