Skip to content
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

Refactor Known Types #202

Merged
merged 6 commits into from Aug 9, 2022
Merged

Refactor Known Types #202

merged 6 commits into from Aug 9, 2022

Conversation

axunonb
Copy link
Collaborator

@axunonb axunonb commented Jul 25, 2022

Closes #197, #93, #88

In case of #88 a byte[] array known type could now be added (instead of using an ICustomSerializer

Known Type related

  • All KnownType<T>.Serialization(...) and KnownType<T>.Deserialization methods have SerializationContext as argument
  • Refactor KnownTypeExtensions: It's now XNamespaceExtensions (IKnowType was not used)
  • Move classes in folder KnownTypes to namespace KnownTypes
  • Rename class KnownTypes to WellKnownTypes and add methods:
    • Add(...)
    • Remove(...)
    • Clear()
    • RestoreDefault()
    • TryGetKnownType(Type? type, out IKnownType? knownType)
  • Add KnownBaseTypeBase<T> as another kind of KnownType<T>
  • Add ExceptionKnownBaseType as the first KnownBaseTypeBase<T>
  • Add ReflectionUtils.IsBaseClassOrSubclassOf(Type subType, string baseName) to determine Exception subclasses
  • Add methods SetFieldValue and SetPropertyValue to ReflectionUtils. They can read/write (also) to private members of base classes. Used for setting the Exception's private _message member.
  • Make IKnownType, KnownTypeBase, DynamicKnownTypeBase, KnownBaseTypeBase and WellKnownTypes public
  • Add RecursionCount as property to SerializationContext to keep recursion under control in IKnownTypes and ICustomSerializers.

Other

  • YAXSerializationOptions now have flag "None = 0". SerializeNullObjects is still the default, and is set in the CTOR of YAXSerializer
  • UdtWrapper CTOR takes SerializerOptions as argument, instead of YAXSerializer
  • MemberWrapper CTOR takes SerializerOptions as argument, instead of YAXSerializer
  • UdtWrapper and MemberWrapper have a property IKnownType? KnownType to avoid looking up known types repetitively
  • Make abstract YAXException CTORs protected
  • Increase test coverage for known types, ReflectionUtils, and overall test coverage
  • Various code fixed red-flagged by SonarCloud
  • Update xmldoc

@axunonb
Copy link
Collaborator Author

axunonb commented Jul 25, 2022

See SonarCloud Quality here

@304NotModified
Copy link
Collaborator

This one needs a merge of #199 (and rebase after it) before review

Main achievements:
* Increase speed by factor 5.5
* Descrease GC pressure by factor 5.5

* Created caches for UdtWrapper and MemberWrapper in new namespace Caching
* Added all unit tests for caching
* Created object pool in namespace Pooling. Using SerializerPool for YAXSerializer, StringBuilderPool for Stringbuilder
* Added all unit tests for pooling
* GenericDeserializationTests and GenericSerializationTests contains tests for all pool items are returned to pools after completing TestFixtures
* Added SetupFixture for PoolSettings.CheckReturnedObjectsExistInPool = true

Code clean-up / miscellaneous:
* extended furhter code sections with "nullable enable"
* Replaced throwing System.Exception by more specific exception types
* Fixed unit test where Assert arguments were mixed-up
* Updated Microsoft.SourceLink.GitHub to v1.1.1
The following methods were moved, because they anyway required an UdtWrapper argument or were static
* GetFieldsToBeSerialized(...)
* IsValidPropertyOrField(...)
*  CanSerializeProperty(...)
* Remove classes MruCache and MruCacheTests
* UdtWrapperCache.DefaultCacheSize = 500
* MemberWrapperCache.DefaultCacheSize = 10000
* SerializerOptions.DefaultMaxRecursion = 50;
* Remove property PoolSettings.IsPoolingEnabled
* Remove "magic zero" as "endless" for MaxRecursion. To achieve old behavior, set it to int.MaxValue
* UdtWrapper CTOR takes SerializerOptions as argument, instead of YAXSerializer
* MemberWrapper CTOR take SerializerOptions as argument, instead of YAXSerializer
* UdtWrapper and MemberWrapper have property IKnownType? KnownType to avoid repeated looking up known types
* All KnownType<T>.Serialization(...) and  KnownType<T>.Deserialization have SerializationContext as argument
* Make IKnownType, KnownTypeAbstract, DynamicKnownTypeAbstract and WellKnownTypes public
* Refactor KnownTypeExtensions to XNamespaceExtensions
* Move classes in folder KnownTypes to namespace KnownTypes
* Rename class KnownTypes to WellKnownTypes and add methods:
  * Add(...)
  * Remove(...)
  * Clear()
  * RestoreDefault()
  * TryGetKnownType(Type? type, out IKnownType? knownType)
* Add KnownBaseTypeAbstract<T> as another kind of KnownType<T>
* Add ExceptionKnownBaseType as the first KnownBaseTypeAbstract<T>
* Add ReflectionUtils.IsBaseClassOrSubclassOf(Type subType, string baseName) to determine Exception subclasses
* Add methods SetFieldValue and SetPropertyValue to ReflectionUtils. They can read/write (also) to private members from base types
* Add RecursionCount as property to SerializationContext
* Add some missing unit tests for ReflectionUtils
* Make abstract YAXException CTORs protected
* YAXSerializationOptions now have flag "None = 0". SerializeNullObjects is still the default, and is set in the CTOR of YAXSerializer
* Increase test coverage for known types, and overall test coverage
* Various code fixed red-flagged by SonarCloud
* Update xmldoc
_TypeCacheBase._instance now only has a private setter. The value is set by SetInstanceVariable(...)
@axunonb axunonb marked this pull request as ready for review July 30, 2022 14:31
@axunonb
Copy link
Collaborator Author

axunonb commented Jul 30, 2022

This one needs a merge of #199 (and rebase after it) before review

Done ;-)

@axunonb
Copy link
Collaborator Author

axunonb commented Aug 4, 2022

@304NotModified ;-)

@axunonb axunonb merged commit 70cde1c into YAXLib:version/4.0 Aug 9, 2022
@axunonb axunonb deleted the pr-known-types branch August 9, 2022 09:45
@304NotModified
Copy link
Collaborator

Sorry, it was too large for me to review. I started it, but it took more time that I had

@axunonb
Copy link
Collaborator Author

axunonb commented Aug 10, 2022

Yes. I thought so. Feel free to post whenever you stumble across sth. that should be improved, like you did with other PRs. Without this commit it was too difficult to move on, because changes to KnownType and CustomSerializer are closely related. I'll post few questions where I'd like to know your opinion before coding.

@axunonb
Copy link
Collaborator Author

axunonb commented Aug 10, 2022

Question 1 ;-)

Make IKnownType, KnownTypeBase, DynamicKnownTypeBase, KnownBaseTypeBase and WellKnownTypes public

This is related to #93. Makes sense this way, or better be more "internal"?

@304NotModified
Copy link
Collaborator

Yes that's indeed #93

I think its a good idea to make them public

axunonb added a commit that referenced this pull request Oct 30, 2022
* Custom Serialization (#181)

* Ese assembly name for checking members for .NET origin (fixes #179) (#180)

* Implement YAXSerializationOptions.DontSerializeNullObjects for deserialization (#177)

Fixes #174

* Added a serialization context when invoking CustomSerializers (#167)

* Added a serialization context when invoking CustomSerializers
* Feature/initial step single responsibility principal (#168)
* Added regions to help make the YAXSerializer more readable.
* Single Responsibility Principal, moved logic related to creating a custom serializer to it's own class.
* Single Responsibility Principal, moved all or at least most logic related to namespaces to it's own class.
Co-authored-by: bob.sanders <bob.sanders@valtech.com>
* Fixes #166 ICustomSerializers may have an interface as the generic argument (#169)
e.g. public class SomeSerializer : ICustomSerializer<ISomeInterface> {
   //...
}
* Update to VS2022 and update NuGet key (#171)
* Update appveyor
* use build worker image "Visual Studio 2022"
* update for expiring NuGet API key
* Update sln to Visual Studio Version 17
* Type handling and related exceptions (#172)
* Fixes #164
* Updated appveyor.yml

* Added GitHub Action for SonarCloud integration (#173)

* Added GitHub Action for SonarCloud integration

* Coverage for line AND branch

* Add generic constructor (#170)

* add generic constructor
* add generic methods
* rename generic filename as requested

* Several updates to PR

* Rebase to latest master
* nullable enable for ISerialilzationContext
* ISerializationContext with new member SerializerOptions
* nullable enable for MemberWrapper
* separate file for SerializationContext
* Test for SerializationContext

* Fix possible null reference warnings

* Fix: No invokation of ICustomSerializer on deserialization

Bug: ICustomSerializer was only called after first deserialization

Reasons:
* In YAXSerializer, HasCustomSerializer was tested BEFORE analyzing the RealType attribute, to it was not called for deserialization
* At the same time, the default deserialization gave the correct result

Measures:
* HasCustomSerializer is tested AFTER analyzing any RealType attribute
* Tests will now fail, if ICustomSerializer is not called

Co-authored-by: prettyv <prettyvanilla@posteo.at>
Co-authored-by: bobduncan <bobsanders13@hotmail.com>

* Trigger SonarCloud also for 'version/**' branches (#182)

* Added IYAXSerializer and proper inheritance for YAXSerializer<T> (#183)

* Added IYAXSerializer and proper inheritance for YAXSerializer<T>

* Added generic test

Co-authored-by: Julian Verdurmen <304NotModified@users.noreply.github.com>

* Remove usage of obsolete constructors and members (#189)

Remove usage of obsolete constructors and members
* All YAXLibTests and DemoApplication updated
* Removed SerializerOptionsTests (containing no tests, but still covered 100%)

Small fixes from review
* Corrected blank + apply latest C# features
* Corrected indent, unused variables in SerializationTest replaced with discard _

* Remove obsolete YAXLib classes and methods  (#190)

Remove obsolete classes and methods

* YAXSerializer: Remove obsolete constructors and members
* Remove class YAXElementValueAlreadyExistsException
* Remove class YAXInvalidFormatProvided
* Correct TypeWrapper method name 'SetYAXSerializerOptions' to 'SetYAXSerializationOptions'

* All (de)serialize tests for the generic and non-generic version (#194)

All serialize tests for the generic and non-generic version

+ small cleanup

formatting

Co-authored-by: Julian Verdurmen <304NotModified@users.noreply.github.com>

* Improve maintainability: SonarCloud Cognitive Complexity <= 20 (#186)

* Fix: EnumWrapper(Type t) throws ArgumentException instead of wrong ArithmeticException
* YAXSerializer split into new internal classes Serialization and Deserialization with existing code (single responsibility)
* Create new methods to remove code duplications, keeping existing code
* Make private method and variable names more self-explanatory, corrected typos
* Remove unused arguments in private methods
* Merge adjacent if statements
* Remove redundant null checks, add missing null checks
* Update xmldoc containing references to non-existing classes/members
* Create internal IYaxMemberLevelAttribute: implemented in MemberWrapper and existing attributes for members
* Create internal IYaxTypeLevelAttribute: implemented in UdtWrapper and existing attributes for types
* Move code from MemberWrapper.ProcessYAXAttribute(object attr) to corresponding IYaxMemberLevelAttribute.Setup(...) of attributes
* Move code from UdtWrapper.ProcessYAXAttribute(object attr) to corresponding IYaxTypeLevelAttribute.Setup(...) of attributes
* Most properties with backing fields are now auto-properties in MemberWrapper and UdtWrapper
* Remove outdated "TODO" comments
* Remove comments containing old code
* Add setter to IRecursionCounter.RecursionCount
* 100% unit test coverage for YAXSerializer and YAXSerializer<T> public members

* Add option to serialize private members from base types (#192)

* Added option YAXSerializableTypeAttribute.IncludePrivateMembersFromBaseTypes
* Added extension method for Type,GetMembers(Type, BindingFlags, bool), used in YAXSerializer.GetFieldsToBeSerialized(UdtWrapper)
* Added property UdtWrapper.IncludePrivateMembersFromBaseTypes
* Added unit tests
* Modfied xmldoc with references to that option
* Fixed xmldoc in YAXSerializationOptions
* Closes #36

* Extend caching and use object pooling for better performance (#199)

* Added/extended Caching and Object Pooling

Main achievements:
* Increase speed by factor 5.5
* Descrease GC pressure by factor 5.5

* Created caches for UdtWrapper and MemberWrapper in new namespace Caching
* Added all unit tests for caching
* Created object pool in namespace Pooling. Using SerializerPool for YAXSerializer, StringBuilderPool for Stringbuilder
* Added all unit tests for pooling
* GenericDeserializationTests and GenericSerializationTests contains tests for all pool items are returned to pools after completing TestFixtures
* Added SetupFixture for PoolSettings.CheckReturnedObjectsExistInPool = true

Code clean-up / miscellaneous:
* extended furhter code sections with "nullable enable"
* Replaced throwing System.Exception by more specific exception types
* Fixed unit test where Assert arguments were mixed-up
* Updated Microsoft.SourceLink.GitHub to v1.1.1

* Use Stringbuilder from pool instead of string concatenation

* Added MaxCacheSize = DefaultCacheSize to MemberWrapperCache

* Changes from review comments

* Remove classes MruCache and MruCacheTests
* UdtWrapperCache.DefaultCacheSize = 500
* MemberWrapperCache.DefaultCacheSize = 10000
* SerializerOptions.DefaultMaxRecursion = 50;
* Remove property PoolSettings.IsPoolingEnabled
* Remove "magic zero" as "endless" for MaxRecursion. To achieve old behavior, set it to int.MaxValue

* Refactoring from review comments

* Move methods from YAXSerializer to UdtWrapper (#200)

* Refactor Known Types (#202)

** Known Type related **

* All KnownType<T>.Serialization(...) and KnownType<T>.Deserialization methods have SerializationContext as argument
* Refactor KnownTypeExtensions: It's now XNamespaceExtensions (IKnowType was not used)
* Move classes in folder KnownTypes to namespace KnownTypes
* Rename class KnownTypes to WellKnownTypes and add methods:
        Add(...)
        Remove(...)
        Clear()
        RestoreDefault()
        TryGetKnownType(Type? type, out IKnownType? knownType)
* Add KnownBaseTypeBase<T> as another kind of KnownType<T>
* Add ExceptionKnownBaseType as the first KnownBaseTypeBase<T>
* Add ReflectionUtils.IsBaseClassOrSubclassOf(Type subType, string baseName) to determine Exception subclasses
* Add methods SetFieldValue and SetPropertyValue to ReflectionUtils. They can read/write (also) to private members of base classes. Used for setting the Exception's private _message member.
* Make IKnownType, KnownTypeBase, DynamicKnownTypeBase, KnownBaseTypeBase and WellKnownTypes public
* Add RecursionCount as property to SerializationContext to keep recursion under control in IKnownTypes and ICustomSerializers.

** Other **

* YAXSerializationOptions now have flag "None = 0". SerializeNullObjects is still the default, and is set in the CTOR of YAXSerializer
* UdtWrapper CTOR takes SerializerOptions as argument, instead of YAXSerializer
* MemberWrapper CTOR takes SerializerOptions as argument, instead of YAXSerializer
* UdtWrapper and MemberWrapper have a property IKnownType? KnownType to avoid looking up known types repetitively
* Make abstract YAXException CTORs protected
* Increase test coverage for known types, ReflectionUtils, and overall test coverage
* Various code fixed red-flagged by SonarCloud
* Update xmldoc

* Refactor custom serialization and known type serialization (#204)

* Resolves #203

**** UdtWrapper ****

Make UdtWrapper.GetFieldsToBeSerialized private, add methods
* UdtWrapper.GetFieldsForSerialization()
* UdtWrapper.GetFieldsForDeserialization(bool)
* Move member-related checks, that are needed for serialization and deserialization from Serialization.SerializeFields(...) and Deserialization.DeserializeDefault(...) to UdtWrapper.GetFieldsToBeSerialized(...)

**** Folder "Custom" (namespace not yet aligned) ****

* ISerializationContext / SerializationContext
  - Refactor:  Members are ITypeContext, IMemberContext?, SerializerOptions, RecursionCount
  - ISerializationContext.ITypeContext will always be set
  - If a member is de/serialized IMemberContext will always be assigned for ICustomSerializer and IKnownType
* ITypeContext / TypeContext
  - Has methods to de/serialize the current type
  - Has methods GetFieldsForSerialization() and GetFieldsForDeserialization
* IMemberContext / MemberContext
  - Has members MemberInfo, FieldInfo?, PropertyInfo?, TypeContext
  - Has method GetValue()
* CustomSerializerWrapper
  - A wrapper for all ICustomSerializers
* Locker, used in Serialization, Deserialization, CustomSerializerWrapper
  - Blocks recursive calls to ICustomSerializers and IKnownTypes
* ICustomSerializer: Update xmldoc for changing element/attribute name
* Refactor Serialization.InvokeCustomSerializer: Code equivalent to Deserialization.InvokeCustomSerializer

**** ExceptionKnownBaseType ****

* Refactor using new features of SerializationContext

**** Invokation of ICustomSerializers ****

* Remove ReflectionBridgeExtensions
* Add CustomSerializerWrapper which includes invokation

**** Other ****

* UdtWrapper.Alias is not nullable
* MemberWrapper.Alias is not nullable
* XMLUtils.ToXmlValue handles null properly

**** Unit tests ****

* Add tests for new features
* Modified existing tests to use new features

* Create Namespace YAXLib.Customization

Included types:
CustomSerializerWrapper, IMemberContext, ISerializationContext, ITypeContext, Locker, MemberContext, SerializationContext, TypeContext

* Add NetStandard2.1 as target framework (#207)

* Add text embedding for XML elements, option to strip invalid XML chars (#208)

* Add NetStandard2.1 as target framework
* Add text embedding for XML elements, strip invalid XML chars
* Added YAXTextEmbeddingAttribute which allows for TextEmbedding.None, TextEmbedding.CData, TextEmbedding.Base64
* Added YAXSerializationOptions.StripInvalidXmlChars to remove all invalid characters from serialization output

* Refactor YAXLib for Nullable Reference Types (#209)

* NRT for YAXLib.Options
* NRT for YAXLib.Pooling
* NRT for YAXLib.KnownTypes
* NRT for YAXLib.Exceptions and ReflectionUtils
* NRT for YAXLib.Enums
* NRT for YAXLib.Customization
* NRT for YAXLib.Caching and YAXLib.Attributes
* NRT for EnumWrapper, StringExtensions, StringUtils, TypeExtensions
* NRT for core classes

YAXSerializer
YAXSerializerOfT
MemberWrapper
UdtWrapper
Serialization
Deserialization
YAXParsingErrors
XmlNamespaceManager
XMLUtils
IYAXSerializer
IRecursionCounter
ICustomSerializer

* Set global 'nullable enable' except YAXLibTests, Demo
* Removed #nullable enable preprocesser directive
* Directory.Build.props: added nullable enable
* YAXLibTests, DemoApplication: set nullable disable in *.csproj

* Integrate changes from PR #208 review

* TypeContext.Deserialize/.Serialize: options may be null (#210)

* Revert TypeContext.De/Serialize: options may be null again

See PR comment
#209 (comment)

* Update ITypeContext

* Bump version 4.0.0-pre.1 (#211)

* NRT enabled for YAXLibTests and DemoApplication (#212)

* csproj files modified with nullable enable
* Fixed possible null references
* YAXLibTests method/type names follow naming convention

* Reformat solution (#213)

Reformat solution
Does not contain any changes in code logic - automated with ReSharper
* Use file-scoped namespace
* Remove unused directives
* Reformat code and embedded xmldoc comments
* Correct typos in xmldoc comments
* Remove remaining (obsolete) "#nullable enable"
* Remove redundant this-qualifier
* Set file-scoped namespace declaration in .editorconfig

* Prepare to merge branch version/4.0 to master

* Update appveyor for version and branch
* Remove destructor from Locker

Co-authored-by: prettyv <prettyvanilla@posteo.at>
Co-authored-by: bobduncan <bobsanders13@hotmail.com>
Co-authored-by: Julian Verdurmen <5808377+304NotModified@users.noreply.github.com>
Co-authored-by: Julian Verdurmen <304NotModified@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants