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
Refactor Known Types #202
Conversation
See SonarCloud Quality here |
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(...)
Done ;-) |
@304NotModified ;-) |
Sorry, it was too large for me to review. I started it, but it took more time that I had |
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. |
Question 1 ;-)
This is related to #93. Makes sense this way, or better be more "internal"? |
Yes that's indeed #93 I think its a good idea to make them public |
* 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>
Closes #197, #93, #88
In case of #88 a
byte[]
array known type could now be added (instead of using anICustomSerializer
Known Type related
KnownType<T>.Serialization(...)
andKnownType<T>.Deserialization
methods haveSerializationContext
as argumentKnownTypeExtensions
: It's nowXNamespaceExtensions
(IKnowType
was not used)KnownTypes
KnownTypes
toWellKnownTypes
and add methods:Add(...)
Remove(...)
Clear()
RestoreDefault()
TryGetKnownType(Type? type, out IKnownType? knownType)
KnownBaseTypeBase<T>
as another kind ofKnownType<T>
ExceptionKnownBaseType
as the firstKnownBaseTypeBase<T>
ReflectionUtils.IsBaseClassOrSubclassOf(Type subType, string baseName)
to determineException
subclassesSetFieldValue
andSetPropertyValue
toReflectionUtils
. They can read/write (also) to private members of base classes. Used for setting theException
's private_message
member.IKnownType
,KnownTypeBase
,DynamicKnownTypeBase
,KnownBaseTypeBase
andWellKnownTypes
publicRecursionCount
as property toSerializationContext
to keep recursion under control inIKnownType
s andICustomSerializer
s.Other
YAXSerializationOptions
now have flag "None = 0
".SerializeNullObjects
is still the default, and is set in the CTOR ofYAXSerializer
UdtWrapper
CTOR takesSerializerOptions
as argument, instead ofYAXSerializer
MemberWrapper
CTOR takesSerializerOptions
as argument, instead ofYAXSerializer
UdtWrapper
andMemberWrapper
have a propertyIKnownType? KnownType
to avoid looking up known types repetitivelyYAXException
CTORs protected