Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 55c1d4e

Browse files
ViktorHoferdanmoseley
authored andcommitted
Release/2.0.0 Desktop <--> Core serialization support (#12300)
* TypeForwardedFrom attributes on coretypes for NetFX serialization (#12059) * TypeForwardedFrom attributes on coretypes for NetFX serialization * ValueTuple added * Removed StubEnvironment typeforwards * Modified FQAN for some special type forwards * Support desktop to core serialization with InternalsVisibleTo for mscorlib * Remove typeforwards from nested types * Removed unused file * DateTime serialization fixed, added attention labels to serialized fields (#12181) * DateTime serialization fixed, added attention labels to serialized fields * CultureAwareComparer serialization fix * Order or property fixed * Remove serializable attribute from OrdinalIgnoreCaseComparer (#12215) * Remove serializable attribute from OrdinalIgnoreCaseComparer * Introducing OrdinalCaseSensitiveComparer to serialize correctly with netfx * Updated PR feedback * Fix gethashcode for ordinal comparer (#12267) Fix GetHashCode for ordinal comparer * Renaming serializable field (#12273)
1 parent f2e50f0 commit 55c1d4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+365
-278
lines changed

src/mscorlib/System.Private.CoreLib.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,6 @@
619619
<Compile Include="$(BclSourcesRoot)\System\Resources\__HResults.cs" />
620620
<Compile Include="$(BclSourcesRoot)\System\Resources\FileBasedResourceGroveler.cs" />
621621
<Compile Include="$(BclSourcesRoot)\System\Resources\IResourceGroveler.cs" />
622-
<Compile Include="$(BclSourcesRoot)\System\Resources\LooselyLinkedResourceReference.cs" />
623622
<Compile Include="$(BclSourcesRoot)\System\Resources\ManifestBasedResourceGroveler.cs" />
624623
<Compile Include="$(BclSourcesRoot)\System\Resources\ResourceManager.cs" />
625624
<Compile Include="$(BclSourcesRoot)\System\Resources\ResourceReader.cs" />

src/mscorlib/shared/System/Char.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace System
2121
{
2222
[Serializable]
2323
[StructLayout(LayoutKind.Sequential)]
24+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
2425
public struct Char : IComparable, IComparable<Char>, IEquatable<Char>, IConvertible
2526
{
2627
//

src/mscorlib/shared/System/Collections/DictionaryEntry.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ namespace System.Collections
99
// A DictionaryEntry holds a key and a value from a dictionary.
1010
// It is returned by IDictionaryEnumerator::GetEntry().
1111
[Serializable]
12+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1213
public struct DictionaryEntry
1314
{
14-
private Object _key;
15-
private Object _value;
15+
private Object _key; // Do not rename (binary serialization)
16+
private Object _value; // Do not rename (binary serialization)
1617

1718
// Constructs a new DictionaryEnumerator by setting the Key
1819
// and Value fields appropriately.

src/mscorlib/shared/System/Collections/Generic/KeyValuePair.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ internal static string PairToString(object key, object value)
4646
// It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
4747
// and IReadOnlyDictionary<TKey, TValue>.
4848
[Serializable]
49+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
4950
public struct KeyValuePair<TKey, TValue>
5051
{
51-
private TKey key; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
52-
private TValue value; // DO NOT change the field name, it's required for compatibility with desktop .NET as it appears in serialization payload.
52+
private TKey key; // Do not rename (binary serialization)
53+
private TValue value; // Do not rename (binary serialization)
5354

5455
public KeyValuePair(TKey key, TValue value)
5556
{

src/mscorlib/shared/System/DateTime.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace System
5454
//
5555
[StructLayout(LayoutKind.Auto)]
5656
[Serializable]
57+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
5758
public partial struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
5859
{
5960
// Number of 100ns ticks per time unit
@@ -125,8 +126,8 @@ public partial struct DateTime : IComparable, IFormattable, IConvertible, ICompa
125126
private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
126127
private const Int32 KindShift = 62;
127128

128-
private const String TicksField = "ticks";
129-
private const String DateDataField = "_dateData";
129+
private const String TicksField = "ticks"; // Do not rename (binary serialization)
130+
private const String DateDataField = "dateData"; // Do not rename (binary serialization)
130131

131132
// The data is stored as an unsigned 64-bit integeter
132133
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value

src/mscorlib/shared/System/DateTimeOffset.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace System
3030

3131
[StructLayout(LayoutKind.Auto)]
3232
[Serializable]
33+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
3334
public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback
3435
{
3536
// Constants
@@ -573,8 +574,8 @@ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext contex
573574
throw new ArgumentNullException(nameof(info));
574575
}
575576

576-
info.AddValue("DateTime", _dateTime);
577-
info.AddValue("OffsetMinutes", _offsetMinutes);
577+
info.AddValue("DateTime", _dateTime); // Do not rename (binary serialization)
578+
info.AddValue("OffsetMinutes", _offsetMinutes); // Do not rename (binary serialization)
578579
}
579580

580581

@@ -585,8 +586,8 @@ private DateTimeOffset(SerializationInfo info, StreamingContext context)
585586
throw new ArgumentNullException(nameof(info));
586587
}
587588

588-
_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime));
589-
_offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16));
589+
_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization)
590+
_offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16)); // Do not rename (binary serialization)
590591
}
591592

592593
// Returns the hash code for this DateTimeOffset.

src/mscorlib/shared/System/Globalization/SortVersion.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace System.Globalization
66
{
77
[Serializable]
8+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
89
public sealed class SortVersion : IEquatable<SortVersion>
910
{
1011
private int m_NlsVersion; // Do not rename (binary serialization)

src/mscorlib/shared/System/StringComparer.cs

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
using System.Collections.Generic;
77
using System.Globalization;
88
using System.Diagnostics.Contracts;
9+
using System.Runtime.Serialization;
910

1011
namespace System
1112
{
1213
[Serializable]
14+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
1315
public abstract class StringComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>
1416
{
1517
private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);
1618
private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true);
17-
private static readonly OrdinalComparer s_ordinal = new OrdinalComparer();
19+
private static readonly OrdinalCaseSensitiveComparer s_ordinal = new OrdinalCaseSensitiveComparer();
1820
private static readonly OrdinalIgnoreCaseComparer s_ordinalIgnoreCase = new OrdinalIgnoreCaseComparer();
1921

2022
public static StringComparer InvariantCulture
@@ -170,30 +172,33 @@ public int GetHashCode(object obj)
170172
}
171173

172174
[Serializable]
175+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
173176
internal sealed class CultureAwareComparer : StringComparer
174177
{
175-
private readonly CompareInfo _compareInfo;
176-
private readonly CompareOptions _options;
178+
private readonly CompareInfo _compareInfo; // Do not rename (binary serialization)
179+
private readonly bool _ignoreCase; // Do not rename (binary serialization)
177180

178181
internal CultureAwareComparer(CultureInfo culture, bool ignoreCase)
179182
{
180183
_compareInfo = culture.CompareInfo;
181-
_options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
184+
_ignoreCase = ignoreCase;
182185
}
183186

187+
private CompareOptions Options => _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
188+
184189
public override int Compare(string x, string y)
185190
{
186191
if (object.ReferenceEquals(x, y)) return 0;
187192
if (x == null) return -1;
188193
if (y == null) return 1;
189-
return _compareInfo.Compare(x, y, _options);
194+
return _compareInfo.Compare(x, y, Options);
190195
}
191196

192197
public override bool Equals(string x, string y)
193198
{
194199
if (object.ReferenceEquals(x, y)) return true;
195200
if (x == null || y == null) return false;
196-
return _compareInfo.Compare(x, y, _options) == 0;
201+
return _compareInfo.Compare(x, y, Options) == 0;
197202
}
198203

199204
public override int GetHashCode(string obj)
@@ -202,7 +207,7 @@ public override int GetHashCode(string obj)
202207
{
203208
throw new ArgumentNullException(nameof(obj));
204209
}
205-
return _compareInfo.GetHashCodeOfString(obj, _options);
210+
return _compareInfo.GetHashCodeOfString(obj, Options);
206211
}
207212

208213
// Equals method for the comparer itself.
@@ -211,20 +216,108 @@ public override bool Equals(object obj)
211216
CultureAwareComparer comparer = obj as CultureAwareComparer;
212217
return
213218
comparer != null &&
214-
_options == comparer._options &&
219+
_ignoreCase == comparer._ignoreCase &&
215220
_compareInfo.Equals(comparer._compareInfo);
216221
}
217222

218223
public override int GetHashCode()
219224
{
220225
int hashCode = _compareInfo.GetHashCode();
221-
return _options == CompareOptions.None ? hashCode : ~hashCode;
226+
return _ignoreCase ? ~hashCode : hashCode;
227+
}
228+
}
229+
230+
[Serializable]
231+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
232+
internal class OrdinalComparer : StringComparer
233+
{
234+
private readonly bool _ignoreCase; // Do not rename (binary serialization)
235+
236+
internal OrdinalComparer(bool ignoreCase)
237+
{
238+
_ignoreCase = ignoreCase;
239+
}
240+
241+
public override int Compare(string x, string y)
242+
{
243+
if (ReferenceEquals(x, y))
244+
return 0;
245+
if (x == null)
246+
return -1;
247+
if (y == null)
248+
return 1;
249+
250+
if (_ignoreCase)
251+
{
252+
return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
253+
}
254+
255+
return string.CompareOrdinal(x, y);
256+
}
257+
258+
public override bool Equals(string x, string y)
259+
{
260+
if (ReferenceEquals(x, y))
261+
return true;
262+
if (x == null || y == null)
263+
return false;
264+
265+
if (_ignoreCase)
266+
{
267+
if (x.Length != y.Length)
268+
{
269+
return false;
270+
}
271+
return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
272+
}
273+
return x.Equals(y);
274+
}
275+
276+
public override int GetHashCode(string obj)
277+
{
278+
if (obj == null)
279+
{
280+
#if CORECLR
281+
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
282+
#else
283+
throw new ArgumentNullException(nameof(obj));
284+
#endif
285+
}
286+
Contract.EndContractBlock();
287+
288+
if (_ignoreCase)
289+
{
290+
return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
291+
}
292+
293+
return obj.GetHashCode();
294+
}
295+
296+
// Equals method for the comparer itself.
297+
public override bool Equals(object obj)
298+
{
299+
OrdinalComparer comparer = obj as OrdinalComparer;
300+
if (comparer == null)
301+
{
302+
return false;
303+
}
304+
return (this._ignoreCase == comparer._ignoreCase);
305+
}
306+
307+
public override int GetHashCode()
308+
{
309+
int hashCode = nameof(OrdinalComparer).GetHashCode();
310+
return _ignoreCase ? (~hashCode) : hashCode;
222311
}
223312
}
224313

225314
[Serializable]
226-
internal sealed class OrdinalComparer : StringComparer
315+
internal sealed class OrdinalCaseSensitiveComparer : OrdinalComparer, ISerializable
227316
{
317+
public OrdinalCaseSensitiveComparer() : base(false)
318+
{
319+
}
320+
228321
public override int Compare(string x, string y) => string.CompareOrdinal(x, y);
229322

230323
public override bool Equals(string x, string y) => string.Equals(x, y);
@@ -242,14 +335,20 @@ public override int GetHashCode(string obj)
242335
return obj.GetHashCode();
243336
}
244337

245-
// Equals/GetHashCode methods for the comparer itself.
246-
public override bool Equals(object obj) => obj is OrdinalComparer;
247-
public override int GetHashCode() => nameof(OrdinalComparer).GetHashCode();
338+
public void GetObjectData(SerializationInfo info, StreamingContext context)
339+
{
340+
info.SetType(typeof(OrdinalComparer));
341+
info.AddValue("_ignoreCase", false);
342+
}
248343
}
249344

250-
[Serializable]
251-
internal sealed class OrdinalIgnoreCaseComparer : StringComparer
345+
[Serializable]
346+
internal sealed class OrdinalIgnoreCaseComparer : OrdinalComparer, ISerializable
252347
{
348+
public OrdinalIgnoreCaseComparer() : base(true)
349+
{
350+
}
351+
253352
public override int Compare(string x, string y) => string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
254353

255354
public override bool Equals(string x, string y) => string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
@@ -267,8 +366,10 @@ public override int GetHashCode(string obj)
267366
return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
268367
}
269368

270-
// Equals/GetHashCode methods for the comparer itself.
271-
public override bool Equals(object obj) => obj is OrdinalIgnoreCaseComparer;
272-
public override int GetHashCode() => nameof(OrdinalIgnoreCaseComparer).GetHashCode();
369+
public void GetObjectData(SerializationInfo info, StreamingContext context)
370+
{
371+
info.SetType(typeof(OrdinalComparer));
372+
info.AddValue("_ignoreCase", true);
373+
}
273374
}
274375
}

src/mscorlib/shared/System/Text/StringBuilder.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace System.Text
3535
// Console.WriteLine(sb2);
3636
//
3737
[Serializable]
38+
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
3839
public sealed partial class StringBuilder : ISerializable
3940
{
4041
// A StringBuilder is internally represented as a linked list of blocks each of which holds
@@ -58,10 +59,11 @@ public sealed partial class StringBuilder : ISerializable
5859
//
5960
//
6061
internal const int DefaultCapacity = 16;
61-
private const String CapacityField = "Capacity";
62-
private const String MaxCapacityField = "m_MaxCapacity";
63-
private const String StringValueField = "m_StringValue";
64-
private const String ThreadIDField = "m_currentThread";
62+
private const String CapacityField = "Capacity"; // Do not rename (binary serialization)
63+
private const String MaxCapacityField = "m_MaxCapacity"; // Do not rename (binary serialization)
64+
private const String StringValueField = "m_StringValue"; // Do not rename (binary serialization)
65+
private const String ThreadIDField = "m_currentThread"; // Do not rename (binary serialization)
66+
6567
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
6668
// Making the maximum chunk size big means less allocation code called, but also more waste
6769
// in unused characters and slower inserts / replaces (since you do need to slide characters over

0 commit comments

Comments
 (0)