-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Use PayloadReader in System.Resources.Extensions #102379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 15 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
241157e
add System.Runtime.Serialization.BinaryFormat with tests
adamsitnik fdbaf50
set IsPackable to false so the package is not published anywhere, mak…
adamsitnik 1da4a10
reference System.Runtime.Serialization.BinaryFormat in System.Resourc…
adamsitnik ba62c25
copy-paste the System.Windows.Forms.BinaryFormat code as is with no m…
adamsitnik f0c20fc
fix compiler errors caused by lack of global usings and supporting ol…
adamsitnik 39dd889
change the namespace from System.Windows.Forms.BinaryFormat to System…
adamsitnik 00608e4
switch
adamsitnik 6354a91
try to handle the type and assembly name mangling
adamsitnik ba41ff0
Revert "try to handle the type and assembly name mangling"
adamsitnik cde8100
use BinaryFormatter as a fallback when we get NotSupportedException e…
adamsitnik 3a90452
fix the bugs I've introduced when porting the code to older monikers
adamsitnik 37200dc
fix the build error and remove outdated comment
adamsitnik 6a36687
add switch and Compat tests that simply reference existing tests
adamsitnik d4de6ee
copy WinForms tests
adamsitnik 1cb10c1
make the WinForms tests compile and pass:
adamsitnik eb0270f
fix the build (when creating a trimmed list, the serialized size must…
adamsitnik 3b4cda3
change public API: ArrayRecord can represent multi-dimensional array …
adamsitnik cabd585
address code review feedback:
adamsitnik a92a528
remove the fallback to BF
adamsitnik 6f6d03f
handle the type name mangling
adamsitnik 891365f
fix the build?
adamsitnik 7a60a3f
Apply suggestions from code review
adamsitnik ec629c9
Apply suggestions from code review
adamsitnik 6fb3a54
Apply suggestions from code review
adamsitnik 0b10f6b
address code review feedback:
adamsitnik a8c3948
don't run drawing tests on systems where drawing is not supported
adamsitnik b57bc2a
add WebSocketException to the exclusion list (because it's implementa…
adamsitnik a7134ef
address code review feedback:
adamsitnik 42e8199
Apply suggestions from code review
adamsitnik 00cb0a8
Apply suggestions from code review
adamsitnik 243ec2e
address code review feedback:
adamsitnik c485e4a
optimize perf for reading arrays of primitive types, but keep it safe…
adamsitnik 3c1e72c
rename ToArray to GetArray and avoid allocating new array if possible…
adamsitnik f175ff6
solve last TODO: fix max size array support by avoiding Int32 overflo…
adamsitnik d524a92
fix the build
adamsitnik 489c66a
Apply suggestions from code review
adamsitnik 697cb0a
address code review feedback:
adamsitnik e3d1a7b
Merge remote-tracking branch 'upstream/main' into plan
adamsitnik fdbd424
improve arrays support:
adamsitnik 3eefd4e
Don't check if serialized DataTable and DataSet produce exact same by…
adamsitnik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
...braries/System.Resources.Extensions/src/BinaryFormat/BinaryFormattedObject.IParseState.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Runtime.Serialization.BinaryFormat; | ||
|
|
||
| namespace System.Resources.Extensions.BinaryFormat; | ||
|
|
||
| internal sealed partial class BinaryFormattedObject | ||
| { | ||
| /// <summary> | ||
| /// Parsing state. | ||
| /// </summary> | ||
| internal interface IParseState | ||
| { | ||
| BinaryReader Reader { get; } | ||
| IReadOnlyDictionary<int, SerializationRecord> RecordMap { get; } | ||
| Options Options { get; } | ||
| ITypeResolver TypeResolver { get; } | ||
| } | ||
| } | ||
23 changes: 23 additions & 0 deletions
23
...aries/System.Resources.Extensions/src/BinaryFormat/BinaryFormattedObject.ITypeResolver.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Reflection.Metadata; | ||
|
|
||
| namespace System.Resources.Extensions.BinaryFormat; | ||
|
|
||
| internal sealed partial class BinaryFormattedObject | ||
| { | ||
| /// <summary> | ||
| /// Resolver for types. | ||
| /// </summary> | ||
| internal interface ITypeResolver | ||
| { | ||
| /// <summary> | ||
| /// Resolves the given type name against the specified library. | ||
| /// </summary> | ||
| [RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String)")] | ||
| [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] | ||
| Type GetType(TypeName typeName); | ||
| } | ||
| } |
38 changes: 38 additions & 0 deletions
38
src/libraries/System.Resources.Extensions/src/BinaryFormat/BinaryFormattedObject.Options.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Runtime.Serialization; | ||
| using System.Runtime.Serialization.Formatters; | ||
|
|
||
| namespace System.Resources.Extensions.BinaryFormat; | ||
|
|
||
| #pragma warning disable SYSLIB0050 // Type or member is obsolete | ||
|
|
||
| internal sealed partial class BinaryFormattedObject | ||
| { | ||
| internal sealed class Options | ||
| { | ||
| /// <summary> | ||
| /// How exactly assembly names need to match for deserialization. | ||
| /// </summary> | ||
|
|
||
adamsitnik marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| public FormatterAssemblyStyle AssemblyMatching { get; set; } = FormatterAssemblyStyle.Simple; | ||
|
|
||
| /// <summary> | ||
| /// Type name binder. | ||
| /// </summary> | ||
| public SerializationBinder? Binder { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Optional type <see cref="ISerializationSurrogate"/> provider. | ||
| /// </summary> | ||
| public ISurrogateSelector? SurrogateSelector { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Streaming context. | ||
| /// </summary> | ||
| public StreamingContext StreamingContext { get; set; } = new(StreamingContextStates.All); | ||
| } | ||
| } | ||
|
|
||
| #pragma warning restore SYSLIB0050 // Type or member is obsolete | ||
30 changes: 30 additions & 0 deletions
30
...ibraries/System.Resources.Extensions/src/BinaryFormat/BinaryFormattedObject.ParseState.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Runtime.Serialization.BinaryFormat; | ||
|
|
||
| namespace System.Resources.Extensions.BinaryFormat; | ||
|
|
||
| internal sealed partial class BinaryFormattedObject | ||
| { | ||
| /// <summary> | ||
| /// Parsing state for <see cref="BinaryFormattedObject"/>. | ||
| /// </summary> | ||
| internal sealed class ParseState : IParseState | ||
| { | ||
| private readonly BinaryFormattedObject _format; | ||
|
|
||
| public ParseState(BinaryReader reader, BinaryFormattedObject format) | ||
| { | ||
| Reader = reader; | ||
| _format = format; | ||
| } | ||
|
|
||
| public BinaryReader Reader { get; } | ||
| public IReadOnlyDictionary<int, SerializationRecord> RecordMap => _format.RecordMap; | ||
| public Options Options => _format._options; | ||
| public ITypeResolver TypeResolver => _format.TypeResolver; | ||
| } | ||
| } |
139 changes: 139 additions & 0 deletions
139
...raries/System.Resources.Extensions/src/BinaryFormat/BinaryFormattedObject.TypeResolver.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Collections.Generic; | ||
| using System.Diagnostics; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.IO; | ||
| using System.Reflection; | ||
| using System.Reflection.Metadata; | ||
| using System.Runtime.Serialization; | ||
| using System.Runtime.Serialization.Formatters; | ||
|
|
||
| #pragma warning disable SYSLIB0050 // Type or member is obsolete | ||
|
|
||
| namespace System.Resources.Extensions.BinaryFormat; | ||
|
|
||
| internal sealed partial class BinaryFormattedObject | ||
| { | ||
| internal sealed class DefaultTypeResolver : ITypeResolver | ||
| { | ||
| private readonly FormatterAssemblyStyle _assemblyMatching; | ||
| private readonly SerializationBinder? _binder; | ||
|
|
||
| private readonly Dictionary<string, Assembly> _assemblies = []; | ||
| private readonly Dictionary<string, Type> _types = []; | ||
|
|
||
| internal DefaultTypeResolver(Options options) | ||
| { | ||
| _assemblyMatching = options.AssemblyMatching; | ||
| _binder = options.Binder; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Resolves the given type name against the specified library. | ||
| /// </summary> | ||
| [RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String)")] | ||
| [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] | ||
| Type ITypeResolver.GetType(TypeName typeName) | ||
| { | ||
| Debug.Assert(typeName.AssemblyName is not null); | ||
|
|
||
| if (_types.TryGetValue(typeName.AssemblyQualifiedName, out Type? cachedType)) | ||
| { | ||
| return cachedType; | ||
| } | ||
|
|
||
| if (_binder?.BindToType(typeName.AssemblyName.FullName, typeName.FullName) is Type binderType) | ||
| { | ||
| // BinaryFormatter is inconsistent about what caching behavior you get with binders. | ||
| // It would always cache the last item from the binder, but wouldn't put the result | ||
| // in the type cache. This could lead to inconsistent results if the binder didn't | ||
| // always return the same result for a given set of strings. Choosing to always cache | ||
| // for performance. | ||
|
|
||
| _types[typeName.AssemblyQualifiedName] = binderType; | ||
| return binderType; | ||
| } | ||
|
|
||
| if (!_assemblies.TryGetValue(typeName.AssemblyName.FullName, out Assembly? assembly)) | ||
| { | ||
| AssemblyName assemblyName = typeName.AssemblyName.ToAssemblyName(); | ||
| try | ||
| { | ||
| assembly = Assembly.Load(assemblyName); | ||
| } | ||
| catch | ||
| { | ||
| if (_assemblyMatching != FormatterAssemblyStyle.Simple) | ||
| { | ||
| throw; | ||
| } | ||
|
|
||
| assembly = Assembly.Load(assemblyName.Name!); | ||
| } | ||
|
|
||
| _assemblies.Add(typeName.AssemblyName.FullName, assembly); | ||
| } | ||
|
|
||
| Type? type = _assemblyMatching != FormatterAssemblyStyle.Simple | ||
| ? assembly.GetType(typeName.FullName) | ||
| : GetSimplyNamedTypeFromAssembly(assembly, typeName); | ||
|
|
||
| _types[typeName.AssemblyQualifiedName] = type ?? throw new SerializationException($"Could not find type '{typeName}'."); | ||
| return type; | ||
| } | ||
|
|
||
| [RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String, Boolean, Boolean)")] | ||
| private static Type? GetSimplyNamedTypeFromAssembly(Assembly assembly, TypeName typeName) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this is effectively a straight copy of the existing |
||
| { | ||
| // Catching any exceptions that could be thrown from a failure on assembly load | ||
| // This is necessary, for example, if there are generic parameters that are qualified | ||
| // with a version of the assembly that predates the one available. | ||
|
|
||
| try | ||
| { | ||
| return assembly.GetType(typeName.FullName, throwOnError: false, ignoreCase: false); | ||
| } | ||
| catch (TypeLoadException) { } | ||
| catch (FileNotFoundException) { } | ||
| catch (FileLoadException) { } | ||
| catch (BadImageFormatException) { } | ||
|
|
||
| return Type.GetType(typeName.FullName, ResolveSimpleAssemblyName, new TopLevelAssemblyTypeResolver(assembly).ResolveType, throwOnError: false); | ||
|
|
||
| static Assembly? ResolveSimpleAssemblyName(AssemblyName assemblyName) | ||
| { | ||
| try | ||
| { | ||
| return Assembly.Load(assemblyName); | ||
| } | ||
| catch { } | ||
|
|
||
| try | ||
| { | ||
| return Assembly.Load(assemblyName.Name!); | ||
| } | ||
| catch { } | ||
|
|
||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private sealed class TopLevelAssemblyTypeResolver | ||
| { | ||
| private readonly Assembly _topLevelAssembly; | ||
|
|
||
| public TopLevelAssemblyTypeResolver(Assembly topLevelAssembly) => _topLevelAssembly = topLevelAssembly; | ||
|
|
||
| [RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String, Boolean, Boolean)")] | ||
| public Type? ResolveType(Assembly? assembly, string simpleTypeName, bool ignoreCase) | ||
| { | ||
| assembly ??= _topLevelAssembly; | ||
| return assembly.GetType(simpleTypeName, throwOnError: false, ignoreCase); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #pragma warning restore SYSLIB0050 // Type or member is obsolete | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.