{"id":50847330,"url":"https://github.com/koszeggy/KGySoft.CoreLibraries","last_synced_at":"2026-07-01T22:00:47.289Z","repository":{"id":50315000,"uuid":"183416532","full_name":"koszeggy/KGySoft.CoreLibraries","owner":"koszeggy","description":"KGy SOFT Core Libraries features high-performance and handy general libraries.","archived":false,"fork":false,"pushed_at":"2026-04-03T10:35:30.000Z","size":150517,"stargazers_count":75,"open_issues_count":0,"forks_count":14,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-03T15:50:25.489Z","etag":null,"topics":["binary-serialization","business-objects","c-sharp","collections","commands","enums","kgysoft","libraries","performance","profiler","reflection","resource-management","serialization","xml-serialization"],"latest_commit_sha":null,"homepage":"https://kgysoft.net/corelibraries","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/koszeggy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"koszeggy","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://paypal.me/koszeggy"]}},"created_at":"2019-04-25T11:00:42.000Z","updated_at":"2026-04-03T10:16:22.000Z","dependencies_parsed_at":"2025-12-16T17:07:16.455Z","dependency_job_id":null,"html_url":"https://github.com/koszeggy/KGySoft.CoreLibraries","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/koszeggy/KGySoft.CoreLibraries","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koszeggy%2FKGySoft.CoreLibraries","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koszeggy%2FKGySoft.CoreLibraries/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koszeggy%2FKGySoft.CoreLibraries/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koszeggy%2FKGySoft.CoreLibraries/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/koszeggy","download_url":"https://codeload.github.com/koszeggy/KGySoft.CoreLibraries/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koszeggy%2FKGySoft.CoreLibraries/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35024365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary-serialization","business-objects","c-sharp","collections","commands","enums","kgysoft","libraries","performance","profiler","reflection","resource-management","serialization","xml-serialization"],"created_at":"2026-06-14T11:00:24.857Z","updated_at":"2026-07-01T22:00:47.280Z","avatar_url":"https://github.com/koszeggy.png","language":"C#","funding_links":["https://ko-fi.com/koszeggy","https://paypal.me/koszeggy"],"categories":["Validation / DataBinding / MVx / Interactions"],"sub_categories":[],"readme":"﻿# KGy SOFT Core Libraries\n\nKGy SOFT Core Libraries offer high-performance and handy general libraries.\nMany of them aim to replace existing APIs of the original .NET framework with more efficient versions.\nMultiple versions of .NET Framework, .NET Core and .NET Standard are supported.\n\n[![Online Help](https://img.shields.io/website/https/koszeggy.github.io/docs/corelibraries.svg?label=online%20help\u0026up_message=available)](https://koszeggy.github.io/docs/corelibraries)\n[![GitHub Repo](https://img.shields.io/github/repo-size/koszeggy/KGySoft.CoreLibraries.svg?label=github)](https://github.com/koszeggy/KGySoft.CoreLibraries)\n[![Nuget](https://img.shields.io/nuget/vpre/KGySoft.CoreLibraries.svg)](https://www.nuget.org/packages/KGySoft.CoreLibraries)\n[![.NET Fiddle](https://img.shields.io/website/https/dotnetfiddle.net/Authors/84474/koszeggy.svg?label=.NET%20Fiddle)](https://dotnetfiddle.net/Authors/84474/koszeggy)\n\n## Table of Contents:\n\u003c!--2. [Project Site](#project-site) TODO: to docs?--\u003e\n1. [Download](#download)\n   - [Download Binaries](#download-binaries)\n   - [Demo Applications](#demo-applications)\n2. [Documentation](#documentation)\n3. [Release Notes](#release-notes)\n4. [Examples](#examples)\n   - [Extensions Methods](#useful-extensions)\n   - [Collections](#high-performance-collections)\n   - [Fast enum handling](#fast-enum-handling)\n   - [Reflection](#alternative-reflection-api)\n   - [Binary Serialization](#binary-serialization)\n   - [XML Serialization](#xml-serialization)\n   - [Dynamic Resource Management](#dynamic-resource-management)\n   - [Business Objects](#business-objects)\n   - [Command Binding](#command-binding)\n   - [Performance Measurement](#performance-measurement)\n5. [License](#license)\n\n## Download:\n\n### Download Binaries:\n\nThe binaries can be downloaded as a NuGet package directly from [nuget.org](https://www.nuget.org/packages/KGySoft.CoreLibraries)\n\nHowever, the preferred way is to install the package in VisualStudio either by looking for the `KGySoft.CoreLibraries` package in the Nuget Package Manager GUI, or by sending the following command at the Package Manager Console prompt:\n\n    PM\u003e Install-Package KGySoft.CoreLibraries\n\n### Demo Applications:\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_ComponentModel.htm\"\u003eKGySoft.ComponentModel\u003c/a\u003e\u003c/code\u003e Features Demo\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n[KGySoft.ComponentModelDemo](https://github.com/koszeggy/KGySoft.ComponentModelDemo) is a desktop application, which focuses mainly on the features of the [KGySoft.ComponentModel](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_ComponentModel.htm) namespace of KGy SOFT Core Libraries (see also the [business objects](#business-objects) and [command binding](#command-binding) examples below). Furthermore, it also provides some useful code samples for using the KGy SOFT Core Libraries in WPF and Windows Forms applications.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/koszeggy/KGySoft.ComponentModelDemo\"\u003e\u003cimg alt=\"Demo application for KGySoft.ComponentModel features\" src=\"https://user-images.githubusercontent.com/27336165/124353286-f0554780-dc05-11eb-8919-6e96ea53e910.png\"/\u003e\u003c/a\u003e\n  \u003cbr/\u003e\u003cem\u003eDemo application for KGySoft.ComponentModel features\u003c/em\u003e\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDemonstration of \u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_Resources.htm\"\u003eKGySoft.Resources\u003c/a\u003e\u003c/code\u003e Features\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nThough [KGy SOFT Imaging Tools](https://github.com/koszeggy/KGySoft.Drawing.Tools#kgy-soft-imaging-tools) is not quite a demo, it perfectly demonstrates how to use [dynamic resource management](#dynamic-resource-management) in a real application that can generate language resources for non-existing localizations, edit and save the changes in .resx files, and apply them on-the-fly without exiting the application.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/koszeggy/KGySoft.Drawing.Tools\"\u003e\u003cimg alt=\"Editing resources in KGy SOFT Imaging Tools\" src=\"https://user-images.githubusercontent.com/27336165/124143008-0a1e4f80-da8b-11eb-8f85-572507b66154.png\"/\u003e\u003c/a\u003e\n  \u003cbr/\u003e\u003cem\u003eEditing resources in KGy SOFT Imaging Tools\u003c/em\u003e\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Some simple console application live examples are also available at [.NET Fiddle](https://dotnetfiddle.net/Authors/84474/koszeggy).\n\n\u003c!--## Project Site\n\nFind the project site at [kgysoft.net](https://kgysoft.net/corelibraries/). TODO: to docs? --\u003e\n\n## Documentation\n\n* You can find the online KGy SOFT Core Libraries documentation [here](https://koszeggy.github.io/docs/corelibraries).\n* See [this](https://github.com/koszeggy/docs) link to access the online documentation of all KGy SOFT libraries.\n\n## Release Notes\n\nSee the [change log](https://github.com/koszeggy/KGySoft.CoreLibraries/blob/master/KGySoft.CoreLibraries/changelog.txt).\n\n## Examples\n\n### Useful Extensions:\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSpan-like types for all platforms\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIn .NET, depending on the targeted platform you can create a `ReadOnlySpan\u003cchar\u003e`/`ReadOnlyMemory\u003cchar\u003e` from a string or a `Span\u003cT\u003e`/`Memory\u003cT\u003e` from an array. In KGy SOFT Core Libraries you can use the [`StringSegment`][StringSegment] and [`ArraySection\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ArraySection_1.htm) in a very similar manner. They are not just available also for older platforms (starting with .NET Framework 3.5) but provide additional features as well.\n\n```cs\n// For strings you can use the AsSegment extensions in a similar way to AsSpan/AsMemory:\nStringSegment segment = \"This is a string\".AsSegment(10); // Contains \"string\" without allocating a new string.\n```\n\n[`StringSegment`][StringSegment] can be cast to `ReadOnlySpan\u003cchar\u003e` (if available on current platform) but it has also some additional features such as [splitting](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_CoreLibraries_StringSegment_Split.htm). And the [`StringSegmentExtensions`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_StringSegmentExtensions.htm) class have several reader methods, which work on [`StringSegment`][StringSegment] type just like the `StringReader` on strings:\n\n[StringSegment]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_StringSegment.htm\n\n```cs\n// Splitting a string into segments without allocating new strings:\nIList\u003cStringSegment\u003e segments = someDelimitedString.AsSegment().Split('|');\n\n// Or, you can use the reader methods so you don't need to allocate even the list:\n// Please note that though StringSegment is immutable, it is passed to the ReadToSeparator extension method\n// as a ref parameter so it can \"consume\" the segment as if it was mutable.\nStringSegment rest = someDelimitedString; // note that implicit cast works, too\nwhile (!rest.IsNull)\n    DoSomenthingWithSegment(rest.ReadToSeparator('|'));\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/Byk0YM).\n\n[`ArraySection\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ArraySection_1.htm), [`Array2D\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_Array2D_1.htm) and [`Array3D\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_Array3D_1.htm) types work similarly but for arrays. They are not just faster than `Memory\u003cT\u003e` (whose `Span` property has some extra cost) but offer some additional features as well:\n\n```cs\n// So far similar to AsSpan or AsMemory extensions, but this is available on all platforms:\nArraySection\u003cbyte\u003e section = myByteArray.AsSection(25, 100); // 100 bytes starting at index 25\n\n// But if you wish you can treat it as a 10x10 two-dimensional array:\nArray2D\u003cbyte\u003e as2d = section.AsArray2D(10, 10);\n\n// 2D indexing works the same way as for a real multidimensional array. But this is actually faster:\nbyte element = as2d[2, 3];\n\n// Slicing works the same way as for ArraySection/Spans:\nArray2D\u003cbyte\u003e someRows = as2d[1..^1]; // same as as2d.Slice(1, as2d.Height - 2)\n\n// Or you can get a simple row:\nArraySection\u003cbyte\u003e singleRow = as2d[0];\n```\n\nPlease note that none of the lines in the example above allocate anything on the heap.\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e [`ArraySection\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ArraySection_1.htm), [`Array2D\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_Array2D_1.htm) and [`Array3D\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_Array3D_1.htm) types have constructors where you can specify an arbitrary capacity. If the targeted platform supports it, then these use array pooling, which can be much faster than allocating new arrays. Do not forget to release the created instances that were created by the allocator constructors.\n\nIf you want to reinterpret the element type of an array, the [`CastArray\u003cTFrom, TTo\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_CastArray_2.htm), [`CastArray2D\u003cTFrom, TTo\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_CastArray2D_2.htm) and [`CastArray3D\u003cTFrom, TTo\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_CastArray3D_2.htm) types can be used similarly to the ones above. Continuing the previous example:\n\n```cs\n// You can reinterpret the element type if you whish:\nCastArray\u003cbyte, Color32\u003e asColors = myByteArray.Cast\u003cbyte, Color32\u003e();\n\n// Now you can access the elements cast to the reinterpreted type:\nColor32 c = asColors[0];\n\n// Or the reference to them (if supported by the compiler you use):\nref Color32 cRef = ref asColors.GetElementReference(0);\n\n// Casts also have their 2D/3D counterparts:\nCastArray2D\u003cbyte, Color32\u003e asColors2D = asColors.As2D(height: 4, width: 6);\n\n// Same as above, but directly from the section:\nasColors2D = section.Cast2D\u003cbyte, Color32\u003e(4, 6);\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_CoreLibraries_DictionaryExtensions_GetValueOrDefault.htm\"\u003eIDictionary\u0026lt;TKey, TValue\u003e.GetValueOrDefault\u003c/a\u003e\u003c/code\u003e extension methods\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n\u003e ℹ️ **Note**\u003cp/\u003e\n\u003e Since then .NET Core 2.0 also introduced a `GetValueOrDefault` method for the `IReadOnlyDictionary\u003cTKey, TValue\u003e` interface. But KGy SOFT's [`IDictionary\u003cTKey, TValue\u003e.GetValueOrDefault`](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_CoreLibraries_DictionaryExtensions_GetValueOrDefault.htm) methods offer more features, such as using a factory delegate if the default value is expensive to evaluate, using a more specific value type than `TValue` (with special handling for `IDictionary\u003cstring, object\u003e` types where you need to specify only one type argument):\n\n```cs\n// old way:\nobject obj;\nint intValue;\nif (dict.TryGetValue(\"Int\", out obj) \u0026\u0026 obj is int)\n    intValue = (int)obj;\n\n// C# 7.0 way:\nif (dict.TryGetValue(\"Int\", out object o) \u0026\u0026 o is int i)\n    intValue = i;\n\n// GetValueOrDefault ways:\nintValue = (int)dict.GetValueOrDefault(\"Int\");\nintValue = dict.GetValueOrDefault(\"Int\", 0);\nintValue = dict.GetValueOrDefault\u003cint\u003e(\"Int\");\n```\n\u003e 💡 **Tip**\u003c/p\u003e\n\u003e Try also [online](https://dotnetfiddle.net/GKSif4).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCollection range operations\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nThe [`AddRange`](https://koszeggy.github.io/docs/corelibraries/html/M_KGySoft_CoreLibraries_CollectionExtensions_AddRange__1.htm) extension method allows you to add multiple elements to any `ICollection\u003cT\u003e` instance. Similarly, [`InsertRange`](https://koszeggy.github.io/docs/corelibraries/html/M_KGySoft_CoreLibraries_ListExtensions_InsertRange__1.htm), [`RemoveRange`](https://koszeggy.github.io/docs/corelibraries/html/M_KGySoft_CoreLibraries_ListExtensions_RemoveRange__1.htm) and [`ReplaceRange`](https://koszeggy.github.io/docs/corelibraries/html/M_KGySoft_CoreLibraries_ListExtensions_ReplaceRange__1.htm) are available for `IList\u003cT\u003e` implementations. You might need to check the `ICollection\u003cT\u003e.IsReadOnly` property before using these methods.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eManipulating \u003ccode\u003eIEnumerable\u003c/code\u003e and \u003ccode\u003eIEnumerable\u0026lt;T\u003e\u003c/code\u003e types by \u003ccode\u003eTry...\u003c/code\u003e methods\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nDepending on the actual implementation inserting/removing/setting elements in an `IEnumerable` type might be possible. See the `Try...` methods of the [`EnumerableExtensions`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_EnumerableExtensions.htm) class. All of these methods have a **Remarks** section in the documentation that precisely describes the conditions when the corresponding method can be used successfully.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_CoreLibraries_ObjectExtensions_Convert.htm\"\u003eObject.Convert\u0026lt;T\u003e\u003c/a\u003e\u003c/code\u003e extension method\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n```cs\n// between convertible types: like the Convert class but supports also enums in both ways\nresult = \"123\".Convert\u003cint\u003e(); // culture can be specified, default is InvariantCulture\nresult = ConsoleColor.Blue.Convert\u003cfloat\u003e();\nresult = 13.Convert\u003cConsoleColor\u003e(); // this would fail by Convert.ChangeType\n        \n// TypeConverters are used if possible:\nresult = \"AADC78003DAB4906826EFD8B2D5CF33D\".Convert\u003cGuid\u003e();\n        \n// New conversions can be registered:\nresult = 42L.Convert\u003cIntPtr\u003e(); // fail\ntypeof(long).RegisterConversion(typeof(IntPtr), (obj, type, culture) =\u003e new IntPtr((long)obj));\nresult = 42L.Convert\u003cIntPtr\u003e(); // success\n        \n// Registered conversions can be used as intermediate steps:\nresult = 'x'.Convert\u003cIntPtr\u003e(); // char =\u003e long =\u003e IntPtr\n        \n// Collection conversion is also supported:\nresult = new List\u003cint\u003e { 1, 0, 0, 1 }.Convert\u003cbool[]\u003e();\nresult = \"Blah\".Convert\u003cList\u003cint\u003e\u003e(); // works because string is an IEnumerable\u003cchar\u003e\nresult = new[] { 'h', 'e', 'l', 'l', 'o' }.Convert\u003cstring\u003e(); // because string has a char[] constructor\nresult = new[] { 1.0m, 2, -1 }.Convert\u003cReadOnlyCollection\u003cstring\u003e\u003e(); // via the IList\u003cT\u003e constructor\n        \n// even between non-generic collections:\nresult = new HashSet\u003cint\u003e { 1, 2, 3 }.Convert\u003cArrayList\u003e();\nresult = new Hashtable { { 1, \"One\" }, { \"Black\", 'x' } }.Convert\u003cDictionary\u003cConsoleColor, string\u003e\u003e();\n```\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/rzg8If).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_CoreLibraries_ObjectExtensions_In.htm\"\u003eObject.In\u003c/a\u003e\u003c/code\u003e extension method\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n```cs\n// old way:\nif (stringValue == \"something\" || stringValue == \"something else\" || stringValue == \"maybe some other value\" || stringValue == \"or...\")\n    DoSomething();\n\n// In method:\nif (stringValue.In(\"something\", \"something else\", \"maybe some other value\", \"or...\"))\n    DoSomething();\n```\n\n\u003e 📝 **Note**\u003c/p\u003e\n\u003e Since C# 9.0 this exact example above can be simplified also by the new `or` keyword. But the `In` method can be used in other cases as well, such as when the values to compare are not constant expressions. Also, when they are too expensive to evaluate in advance, you can use the `In` overload that accepts a collection of delegates.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_RandomExtensions.htm\"\u003eRandomExtensions\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n```cs\n// Or FastRandom for the fastest results, or SecureRandom for cryptographically safe results.\nvar rnd = new Random();\n\n// Next... for all simple types:\nrnd.NextBoolean();\nrnd.NextDouble(Double.PositiveInfinity); // see also the overloads\nrnd.NextString(); // see also the overloads\nrnd.NextDateTime(); // also NextDate, NextDateTimeOffset, NextTimeSpan\nrnd.NextEnum\u003cConsoleColor\u003e();\n// and NextByte, NextSByte, NextInt16, NextDecimal, etc.\n\n// NextObject: for practically anything. See also GenerateObjectSettings.\nrnd.NextObject\u003cPerson\u003e(); // custom type\nrnd.NextObject\u003c(int, string)\u003e(); // tuple\nrnd.NextObject\u003cIConvertible\u003e(); // interface implementation\nrnd.NextObject\u003cMarshalByRefObject\u003e(); // abstract type implementation\nrnd.NextObject\u003cint[]\u003e(); // array\nrnd.NextObject\u003cIList\u003cIConvertible\u003e\u003e(); // some collection of an interface\nrnd.NextObject\u003cFunc\u003cDateTime\u003e\u003e(); // delegate with random result\n\n// specific type for object (useful for non-generic collections)\nrnd.NextObject\u003cArrayList\u003e(new GenerateObjectSettings { SubstitutionForObjectType = typeof(ConsoleColor) };\n\n// literally any random object\nrnd.NextObject\u003cobject\u003e(new GenerateObjectSettings { AllowDerivedTypesForNonSealedClasses = true });\n```\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/EPHRIx).\n\u003c/details\u003e\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Find more extensions in the [online documentation](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_CoreLibraries.htm).\n\n### High Performance Collections:\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_Cache_2.htm\"\u003eCache\u0026lt;TKey, TValue\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nA `Dictionary`-like type with a specified capacity. If the cache is full and new items have to be stored, then the oldest element (or the least recent used one, depending on `Behavior`) is dropped from the cache.\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e To obtain a thread-safe cache accessor it is recommended to use the [`ThreadSafeCacheFactory`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeCacheFactory.htm) class, where you can configure the characteristics of the cache to create. You can create completely lock-free caches, or caches with strict capacity management, expiring values, etc. See the ***Remarks*** section of the [`ThreadSafeCacheFactory.Create`](https://koszeggy.github.io/docs/corelibraries/html/M_KGySoft_Collections_ThreadSafeCacheFactory_Create__2_1.htm) method for details.\n\nIf an item loader is passed to the constructor, then it is enough only to read the cache via the indexer and the corresponding item will be transparently loaded when necessary.\n\n```cs\n// instantiating the cache by a loader method and a capacity of 1000 possible items\nvar personCache = new Cache\u003cint, Person\u003e(LoadPersonById, 1000);\n\n// you only need to read the cache:\nvar person = personCache[id];\n\n// If a cache instance is accessed from multiple threads use it from a thread safe accessor.\n// The item loader can be protected from being called concurrently.\n// Similarly to ConcurrentDictionary, this is false by default.\nvar threadSafeCache = personCache.GetThreadSafeAccessor(protectItemLoader: false);\n\nperson = threadSafeCache[id];\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/YGDY9c).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeDictionary_2.htm\"\u003eThreadSafeDictionary\u0026lt;TKey, TValue\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nSimilar to `ConcurrentDictionary` but has a bit different characteristic and can be used even in .NET Framework 3.5 where `ConcurrentDictionary` is not available. It can be a good alternative when a fixed number of keys have to be stored or when the `Count` property has to be frequently accessed, which is particularly slow at `ConcurrentDictionary`. See the ***Remarks*** section of the [`ThreadSafeDictionary\u003cTKey, TValue\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeDictionary_2.htm) class for details, including speed comparison of different members.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeHashSet_1.htm\"\u003eThreadSafeHashSet\u0026lt;T\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIn .NET still there is no `ConcurrentHashSet\u003cT\u003e` type. One option is to use a `ConcurrentDictionary\u003cTKey, TValue\u003e` with ignored values. Another option is to use the [`ThreadSafeHashSet\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeHashSet_1.htm) class, which uses a very similar approach to [`ThreadSafeDictionary\u003cTKey, TValue\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_ThreadSafeDictionary_2.htm): when used with a limited number of items, or when new items are rarely added compared to a contains check, then it may become practically lock-free.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_StringKeyedDictionary_1.htm\"\u003eStringKeyedDictionary\u0026lt;TValue\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nActs as a regular `IDictionary\u003cstring, TValue\u003e` but as an [`IStringKeyedDictionary\u003cTValue\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_IStringKeyedDictionary_1.htm) interface implementation, it supports accessing its values also by [`StringSegment`][StringSegment] or `ReadOnlySpan\u003cchar\u003e` keys. To use custom string comparison you can pass a [`StringSegmentComparer`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_StringSegmentComparer.htm) instance to the constructors, which allows string comparisons by `string`, [`StringSegment`][StringSegment] and `ReadOnlySpan\u003cchar\u003e` instances.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Collections_CircularList_1.htm\"\u003eCircularList\u0026lt;T\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nFully compatible with `List\u003cT\u003e` but maintains a dynamic start/end position of the stored elements internally, which makes it very fast when elements are added/removed at the first position. It has also optimized range operations and can return both value type and reference type enumerators depending on the used context.\n\n```cs\nvar clist = new CircularList\u003cint\u003e(Enumerable.Range(0, 1000));\n\n// or by ToCircularList:\nclist = Enumerable.Range(0, 1000).ToCircularList();\n\n// AddFirst/AddLast/RemoveFirst/RemoveLast\nclist.AddFirst(-1); // same as clist.Insert(0, -1); (much faster than List\u003cT\u003e)\nclist.RemoveFirst(); // same as clist.RemoveAt(0); (much faster than List\u003cT\u003e)\n\n// if the inserted collection is not ICollection\u003cT\u003e, then List\u003cT\u003e is especially slow here\n// because it inserts the items one by one and shifts the elements in every iteration\nclist.InsertRange(0, Enumerable.Range(-500, 500));\n\n// When enumerated by LINQ expressions, List\u003cT\u003e is not so effective because of its boxed\n// value type enumerator. In these cases CircularList returns a reference type enumerator.\nConsole.WriteLine(clist.SkipWhile(i =\u003e i \u003c 0).Count());\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ObservableBindingList_1.htm\"\u003eObservableBindingList\u0026lt;T\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nCombines the features of `IBindingList` implementations (such as `BindingList\u003cT\u003e`) and `INotifyCollectionChanged` implementations (such as `ObservableCollection\u003cT\u003e`). It makes it an ideal collection type in many cases (such as in a technology-agnostic View-Model layer) because it can used in practically any UI environments. By default it is initialized by a [`SortableBindingList\u003cT\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SortableBindingList_1.htm) but can wrap any `IList\u003cT\u003e` implementation.\n\u003c/details\u003e\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e See more collections in the [`KGySoft.Collections`](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_Collections.htm), [`KGySoft.Collections.ObjectModel`](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_Collections_ObjectModel.htm) and [`KGySoft.ComponentModel`](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_ComponentModel.htm) namespaces.\n\n### Fast Enum Handling\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_Enum_1.htm\"\u003eEnum\u0026lt;TEnum\u003e\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIn .NET Framework some enum operations used to be legendarily slow. Back then I created the static [`Enum\u003cTEnum\u003e`][enum] and [`EnumComparer\u003cTEnum\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_EnumComparer_1.htm) classes, which provide must faster enum operations than the `System.Enum` type. Since then, the performance has been radically improved, especially in .NET Core, so the difference became much narrower, though it [still exists](https://dotnetfiddle.net/xNTnLE).\n\nSo today the main benefit of using the [`Enum\u003cTEnum\u003e`][enum] class is its extra features and maybe the support of formatting/parsing to and from `Span\u003cchar\u003e`/`ReadOnlySpan\u003cchar\u003e` types, which is missing at `System.Enum` on many platform versions. And if you target older frameworks, which can't use `ReadOnlySpan\u003cchar\u003e`, you still can use the `Parse`/`TryParse` overloads that accept [`StringSegment`][StringSegment] parameters.\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e See the performance comparison in .NET Core and try it [online](https://dotnetfiddle.net/xNTnLE).\n\n[enum]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_CoreLibraries_Enum_1.htm\n\u003c/details\u003e\n\n### Alternative Reflection API\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eAccessors - the performant way\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nThere are four public classes derived from [`MemberAccessor`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_MemberAccessor.htm), which can be used where you would use `MemberInfo` instances. All of them support generic access in some specialized cases for even better performance. But even the non-generic access, which can be used in all cases, is at least one order of magnitude faster than system reflection. The following table summarizes the relation between the system reflection types and their KGy SOFT counterpart:\n\n| System Type                    | KGy SOFT Type                 |\n|--------------------------------|-------------------------------|\n| `FieldInfo`                    | [`FieldAccessor`][fa]         |\n| `PropertyInfo`                 | [`PropertyAccessor`][pa]      |\n| `MethodInfo`                   | [`MethodAccessor`][ma]        |\n| `ConstructorInfo`, `Activator` | [`CreateIstanceAccessor`][ca] |\n\n[fa]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_FieldAccessor.htm\n[pa]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_PropertyAccessor.htm\n[ma]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_MethodAccessor.htm\n[ca]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_CreateInstanceAccessor.htm\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e See the links in the table above for performance comparison examples.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_Reflector.htm\"\u003eReflector\u003c/a\u003e\u003c/code\u003e class - the convenient way\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIf convenience is priority, then the [`Reflector`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Reflection_Reflector.htm) class offers every functionality you need to use for reflection. While the accessors above can be obtained by a `MemberInfo` instance, the `Reflector` can be used even by name. The following example demonstrates this for methods:\n\n```cs\n// Any method by MethodInfo:\nMethodInfo method = typeof(MyType).GetMethod(\"MyMethod\");\n\nresult = Reflector.InvokeMethod(instance, method, param1, param2); // by Reflector\nresult = method.Invoke(instance, new object[] { param1, param2 }); // the old (slow) way\nresult = MethodAccessor.GetAccessor(method).Invoke(instance, param1, param2); // by accessor (fast)\n\n// Instance method by name (can be non-public, even in base classes):\nresult = Reflector.InvokeMethod(instance, \"MethodName\", param1, param2);\n\n// Static method by name (can be non-public, even in base classes):\nresult = Reflector.InvokeMethod(typeof(MyType), \"MethodName\", param1, param2);\n\n// Even generic methods are supported:\nresult = Reflector.InvokeMethod(instance, \"MethodName\", new[] { typeof(GenericArg) }, param1, param2);\n\n// If you are not sure whether a method by the specified name exists use TryInvokeMethod:\nbool invoked = Reflector.TryInvokeMethod(instance, \"MethodMaybeExists\", out result, param1, param2);\n```\n\n\u003e 📝 **Note**\u003cp/\u003e\n\u003e `Try...` methods return false if a matching member with the given name/parameters cannot be found. However, if a member could be successfully invoked, which threw an exception, then this exception will be thrown further.\n\u003c/details\u003e\n\n### Serialization\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eBinary Serialization\u003c/strong\u003e\u003ca id=\"binary-serialization\"/\u003e\u003c/summary\u003e\u003cp/\u003e\n\n\u003e 🔒 **Security Note**\u003cp/\u003e\n\u003e If the serialization stream may come from an untrusted source (e.g. remote service, file or database), then make sure you enable the [`SafeMode`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Serialization_Binary_BinarySerializationOptions.htm) for the deserialization. By doing so all custom types that are stored by assembly identity or by full name must be explicitly declared as expected types (this is not needed for natively supported types, which are not stored by name). Without using this option (or some additional security for the serialization stream) binary serialization is safe only if both the serialization and deserialization happens in the same process, such as creating in-memory snapshots of objects (e.g. for undo/redo functionality) or to create bitwise deep clones. See the security notes at the **Remarks** section of the [`BinarySerializationFormatter`][bsf] class for more details.\n\n[`BinarySerializationFormatter`][bsf] serves the same purpose as `BinaryFormatter` but it fixes a lot of security concerns `BinaryFormatter` suffered from and in most cases produces much compact serialized data with a better performance. It supports many core types natively, including many collections and newer basic types that are not marked serializable anymore (e.g. `Half`, `Rune`, `DateOnly`, `TimeOnly`, etc.). Native support means that serialization of those types does not involve storing assembly and type names at all, which ensures very compact sizes as well as their safe deserialization on every possible platform. Apart from the natively supported types it works similarly to `BinaryFormatter`: uses recursive serialization of fields and supports the full binary serialization infrastructure including `ISerializable`, `IDeserializationCallback`, `IObjectReference`, serialization method attributes, binder and surrogates support. Please note though that in safe mode no custom binders and surrogates are allowed to use.\n\nEven if used in a secure environment or on a cryptographically secured channel, binary serialization of custom types is not quite recommended when communicating between remote entities, because by default custom serialization relies on private implementation (ie. field names). In such cases use messages created exclusively from the natively supported types (see them at [`BinarySerializationFormatter`][bsf]) so it can be used like some `ProtoBuf` but with much more available predefined types. If you really need to use custom types between remote endpoints, then it is recommended to use message types that can be completely restored by public fields and properties so you can use a text-based serializer, eg. an [`XML serializer`](#xml-serialization).\n\nBinary serialization functions are available via the static [`BinarySerializer`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Serialization_Binary_BinarySerializer.htm) class and by the [`BinarySerializationFormatter`][bsf] type.\n\n```cs\n// Simple way: by the static BinarySerializer class\nbyte[] rawData = BinarySerializer.Serialize(instance); // to byte[]\nBinarySerializer.SerializeToStream(stream, instance); // to Stream\nBinarySerializer.SerializeByWriter(writer, instance); // by BinaryWriter\n\n// or explicitly by a BinarySerializationFormatter instance:\nrawData = new BinarySerializationFormatter().Serialize(instance);\n\n// Deserialization:\nobj = BinarySerializer.Deserialize\u003cMyClass\u003e(rawData); // from byte[]\nobj = BinarySerializer.DeserializeFromStream\u003cMyClass\u003e(stream); // from Stream\nobj = BinarySerializer.DeserializeByReader\u003cMyClass\u003e(reader); // by BinaryReader\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/nQfFrQ).\n\nThe [`BinarySerializationFormatter`][bsf] supports many types and collections natively (see the link), which has more benefits: these types are serialized without any assembly information and the result is very compact as well. Additionally, you can use the `BinarySerializationOptions.OmitAssemblyQualifiedNames` flag to omit assembly information on serialization, which reduces the size of the output even more, and more importantly, it makes impossible to load assemblies during the deserialization even if the `BinarySerializationOptions.SafeMode` is not used during the deserialization.\n\n[bsf]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Serialization_Binary_BinarySerializationFormatter.htm\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eXML Serialization\u003c/strong\u003e\u003ca id=\"xml-serialization\"/\u003e\u003c/summary\u003e\u003cp/\u003e\n\n\u003e 🔒 **Security Note**\u003cp/\u003e\n\u003e KGy SOFT's [`XmlSerializer`][xml] is a polymorphic serializer. If the serialized content comes from an untrusted source make sure you use its [`DeserializeSafe`](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_Serialization_Xml_XmlSerializer_DeserializeSafe.htm)/[`DeserializeContentSafe`](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_Serialization_Xml_XmlSerializer_DeserializeContentSafe.htm) methods that disallow loading assemblies during the deserialization even if types are specified with their assembly qualified names, and make it necessary to name every custom type that are expected in the serialization XML. See the security notes at the **Remarks** section of the [`XmlSerializer`][xml] class for more details.\n\nUnlike binary serialization, which is meant to save the bitwise content of an object, the [`XmlSerializer`][xml] can save and restore the public properties and fields. Meaning, it cannot guarantee that the original state of an object can be fully restored unless it is completely exposed by public members. The [`XmlSerializer`][xml] can be a good choice for saving configurations or components whose state can be edited in a property grid, for example.\n\nTherefore [`XmlSerializer`][xml] supports several `System.ComponentModel` attributes and techniques such as `TypeConverterAttribute`, `DefaultValueAttribute`, `DesignerSerializationVisibilityAttribute` and even the `ShouldSerialize...` methods.\n\n```cs\n// A good candidate for XML serialization:\npublic class Person\n{\n    public string FirstName { get; set; }\n\n    [DefaultValue(null)] // will not be serialized if null\n    public string MiddleName { get; set; }\n\n    public string LastName { get; set; }\n\n    public DateTime BirthDate { get; set; }\n\n    // System serializer fails here: the property has no setter and its type cannot be instantiated.\n    public IList\u003cstring\u003e PhoneNumbers { get; } = new Collection\u003cstring\u003e();\n}\n```\n\nAnd the serialization:\n\n```cs\nvar person = ThreadSafeRandom.Instance.NextObject\u003cPerson\u003e();\nvar options = XmlSerializationOptions.RecursiveSerializationAsFallback;\n\n// serializing into XElement\nXElement element = XmlSerializer.Serialize(person, options);\nvar clone = XmlSerializer.DeserializeSafe\u003cPerson\u003e(element);\n\n// serializing into file/Stream/TextWriter/XmlWriter are also supported: An XmlWriter will be used\nvar sb = new StringBuilder();\nXmlSerializer.Serialize(new StringWriter(sb), person, options);\nclone = XmlSerializer.DeserializeSafe\u003cPerson\u003e(new StringReader(sb.ToString()));\n\nConsole.WriteLine(sb);\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/M2dfrx).\n\nIf a root object has a non-default constructor, its content still can be serialized and deserialized by the `SerializeContent`/`DeserializeContent[Safe]` methods:\n\n```cs\npublic class MyComponent\n{\n    // there is no default constructor\n    public MyComponent(Guid id) =\u003e Id = id;\n\n    // read-only property: will not be serialized unless forced by the\n    // ForcedSerializationOfReadOnlyMembersAndCollections option\n    public Guid Id { get; }\n\n    // this tells the serializer to allow recursive serialization for this non-common type\n    // without using the RecursiveSerializationAsFallback option\n    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]\n    public Person Person { get; set; }\n}\n```\n\nWhen serializing such an instance we need to emit a root element explicitly and on deserialization we need to create an empty `MyComponent` instance manually:\n\n```cs\nvar instance = new MyComponent(Guid.NewGuid()) { Person = person };\n\n// serialization (now into XElement but XmlWriter is also supported):\nvar root = new XElement(\"SomeRootElement\");\nXmlSerializer.SerializeContent(root, instance);\n\n// deserialization (now from XElement but XmlReader is also supported):\nvar cloneWithNewId = new MyComponent(Guid.NewGuid());\nXmlSerializer.DeserializeContent(root, cloneWithNewId);\n```\n\n[xml]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Serialization_Xml_XmlSerializer.htm\n\u003c/details\u003e\n\n### Dynamic Resource Management\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eOverview\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e For a real-life example see also the [KGy SOFT Imaging Tools](https://github.com/koszeggy/KGySoft.Drawing.Tools#localization) application that supports creating and applying new localizations on-the-fly, from within the application.\n\nThe KGy SOFT Core Libraries contain numerous classes for working with resources directly from .resx files. Some classes can be familiar from the .NET Framework. For example, [`ResXResourceReader`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_ResXResourceReader.htm), [`ResXResourceWriter`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_ResXResourceWriter.htm) and [`ResXResourceSet`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_ResXResourceSet.htm) are reimplemented by referencing only the core system assemblies (the original versions of these reside in `System.Windows.Forms.dll`, which cannot be used on all platforms) and they got a bunch of improvements at the same time. Most importantly, they all have a `SafeMode` property, which guarantees that no assembly loading and deserialization occurs unless it is explicitly requested. But even if `SafeMode` is false, an item is not deserialized until it is explicitly obtained. Or, the [`ResXResourceSet`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_ResXResourceSet.htm) class is now a read-write collection and the changes can be saved in a new .resx file (see the links above for details and comparisons and examples).\n\nOn top of those, KGy SOFT Core Libraries introduce a sort of new types that can be used the same way as a standard `ResourceManager` class:\n- [`ResXResourceManager`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_ResXResourceManager.htm) works the same way as the regular `ResourceManager` but works on .resx files instead of compiled resources and supports adding and saving new resources, .resx metadata and assembly aliases.\n- The [`HybridResourceManager`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_HybridResourceManager.htm) is able to work both with compiled and .resx resources even at the same time: it can be used to override the compiled resources with .resx content.\n- The [`DynamicResourceManager`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_DynamicResourceManager.htm) can be used to generate new .resx files automatically for languages without a localization. The KGy SOFT Libraries also use `DynamicResourceManager` instances to maintain their resources. The library assemblies are compiled only with the English resources but any consumer library or application can enable the .resx expansion for any language.\n\n\u003e 💡 **Tip**\u003c/p\u003e\n\u003e See the **Remarks** section of the [`KGySoft.Resources`](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_Resources.htm) namespace description, which may help you to choose the most appropriate class for your needs.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eEnabling the localization of the Core Libraries resources\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n```cs\n// Just pick a language for your application\nLanguageSettings.DisplayLanguage = CultureInfo.GetCultureInfo(\"de-DE\");\n\n// Opt-in using .resx files (for all `DynamicResourceManager` instances, which are configured to obtain\n// their configuration from LanguageSettings):\nLanguageSettings.DynamicResourceManagersSource = ResourceManagerSources.CompiledAndResX;\n\n// When you access a resource for the first time for a new language, a new resource set will be generated.\n// This is saved automatically when you exit the application\nConsole.WriteLine(PublicResources.ArgumentNull);\n```\n\nThe example above will print a prefixed English message for the first time: `[T]Value cannot be null.`. Find the newly saved .resx file and look for the untranslated resources with the `[T]` prefix. After saving an edited resource file the example will print the localized message.\n\n\u003e See a complete example at the [`LanguageSettins`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_LanguageSettings.htm) class.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCreating dynamically localizable resources for an application or class library\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nSee the [step-by step description](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_DynamicResourceManager.htm#recommendation) at the [`DynamicResourceManager`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Resources_DynamicResourceManager.htm) class.\n\u003c/details\u003e\n\n### Business Objects\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eOverview\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nThe [`KGySoft.ComponentModel`](https://koszeggy.github.io/docs/corelibraries/html/N_KGySoft_ComponentModel.htm) namespace contains several types that can be used as base type for model classes, view-model objects or other kind of business objects:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Base classes for business objects\" src=\"https://user-images.githubusercontent.com/27336165/124354011-23013f00-dc0a-11eb-9f53-d7aec8e6f15b.png\"/\u003e\n  \u003cbr/\u003e\u003cem\u003eBase classes for business objects\u003c/em\u003e\n\u003c/p\u003e\n\n- [`ObservableObjectBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ObservableObjectBase.htm): The simplest class, supports change notification via the `INotifyPropertyChanged` interface and can tell whether any of the properties have been modified. Provides protected members for maintaining properties.\n- [`PersistableObjectBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_PersistableObjectBase.htm): Extends the `ObservableObjectBase` class by implementing the [`IPersistableObject`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_IPersistableObject.htm) interface, which makes possible to access and manipulate the internal property storage.\n- [`UndoableObjectBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_UndoableObjectBase.htm): Adds step-by-step undo/redo functionality to the `PersistableObjectBase` type. This is achieved by implementing a flexible [`ICanUndoRedo`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICanUndoRedo.htm) interface. Implements also the standard `System.ComponentModel.IRevertibleChangeTracking` interface.\n- [`EditableObjectBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_EditableObjectBase.htm): Adds committable and revertible editing functionality to the `PersistableObjectBase` type. The editing sessions can be nested. This is achieved by implementing a flexible [`ICanEdit`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICanEdit.htm) interface but implements also the standard `System.ComponentModel.IEditableObject` interface, which is already supported by multiple already existing controls in the various graphical user environments.\n- [`ValidatingObjectBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ValidatingObjectBase.htm): Adds business validation features to the `PersistableObjectBase` type. This is achieved by implementing a flexible [`IValidatingObject`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_IValidatingObject.htm) interface, which provides multiple validation levels for each properties. Implements also the standard `System.ComponentModel.IDataErrorInfo` interface, which is the oldest and thus the most widely supported standard validation technique in the various GUI frameworks.\n- [`ModelBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ModelBase.htm): Unifies the features of all of the classes above.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eExample\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nThe following example demonstrates a possible model class with validation:\n\n```cs\npublic class MyModel : ValidatingObjectBase\n{\n    // A simple integer property (with zero default value).\n    // Until the property is set no value is stored internally.\n    public int IntProperty { get =\u003e Get\u003cint\u003e(); set =\u003e Set(value); }\n\n    // An int property with default value. Until the property is set the default will be returned.\n    public int IntPropertyCustomDefault { get =\u003e Get(-1); set =\u003e Set(value); }\n\n    // If the default value is a complex one, which should not be evaluated each time\n    // you can provide a factory for it.\n    // When this property is read for the first time without setting it before\n    // the provided delegate will be invoked and the returned default value is stored without triggering\n    // the PropertyChanged event.\n    public MyComplexType ComplexProperty { get =\u003e Get(() =\u003e new MyComplexType()); set =\u003e Set(value); }\n\n    // You can use regular properties to prevent raising the events\n    // and not to store the value in the internal storage.\n    // The OnPropertyChanged method still can be called explicitly to raise the PropertyChanged event.\n    public int UntrackedProperty { get; set; }\n\n    public int Id { get =\u003e Get\u003cint\u003e(); set =\u003e Set(value); }\n    public string Name { get =\u003e Get\u003cstring\u003e(); set =\u003e Set(value); }\n\n    protected override ValidationResultsCollection DoValidation()\n    {\n        var result = new ValidationResultsCollection();\n\n        // info\n        if (Id == 0)\n            result.AddInfo(nameof(Id), \"This will be considered as a new object when saved\");\n\n        // warning\n        if (Id \u003c 0)\n            result.AddWarning(nameof(Id), $\"{nameof(Id)} is recommended to be greater or equal to 0.\");\n\n        // error\n        if (String.IsNullOrEmpty(Name))\n            result.AddError(nameof(Name), $\"{nameof(Name)} must not be null or empty.\");\n\n        return result;\n    }\n}\n```\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e See the [KGySoft.ComponentModelDemo](https://github.com/koszeggy/KGySoft.ComponentModelDemo) repository to try business objects in action\n\u003c/details\u003e\n\n### Command Binding\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eOverview\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nKGy SOFT Core Libraries contain a simple, technology-agnostic implementation of the Command pattern. Commands are actually advanced event handlers. The main benefit of using commands is that they can be bound to multiple sources and targets, and unsubscription from sources is handled automatically when the binding is disposed (no more memory leaks due to delegates and you don't even need to use heavy-weight weak events).\n\nA command is represented by the [`ICommand`][ICommand] interface (see some examples also in the link). There are four pairs of predefined `ICommand` implementations that can accept delegate handlers:\n- [`SimpleCommand`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SimpleCommand.htm) and [`SimpleCommand\u003cTParam\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SimpleCommand_1.htm)\n- [`TargetedCommand\u003cTTarget\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_TargetedCommand_1.htm) and [`TargetedCommand\u003cTTarget, TParam\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_TargetedCommand_2.htm)\n- [`SourceAwareCommand\u003cTEventArgs\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SourceAwareCommand_1.htm) and [`SourceAwareCommand\u003cTEventArgs, TParam\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SourceAwareCommand_2.htm)\n- [`SourceAwareTargetedCommand\u003cTEventArgs, TTarget\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SourceAwareTargetedCommand_2.htm) and [`SourceAwareTargetedCommand\u003cTEventArgs, TTarget, TParam\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_SourceAwareTargetedCommand_3.htm)\n\nA command itself is a static logic. Every dynamic attribute of a command (including the Enabled and other arbitrary states but also the sources and targets) belong to the binding(s).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommand.htm\"\u003eICommand\u003c/a\u003e\u003c/code\u003e and \u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommandBinding.htm\"\u003eICommandBinding\u003c/a\u003e\u003c/code\u003e interfaces\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\n```cs\npublic static class MyCommands\n{\n    public static readonly ICommand PasteCommand = new TargetedCommand\u003cTextBoxBase\u003e(tb =\u003e tb.Paste());\n\n    public static readonly ICommand ReplaceTextCommand = new TargetedCommand\u003cControl, string\u003e((target, value) =\u003e target.Text = value);\n}\n```\n\nTo use a command it has to be bound to one or more sources (and to some targets if the command is targeted). To create a binding the `CreateBinding` extension method can be used:\n\n```cs\nvar binding = MyCommands.PasteCommand.CreateBinding(menuItemPaste, \"Click\", textBox);\n\n// Alternative way by fluent syntax: (also allows to add multiple sources)\nbinding = MyCommands.PasteCommand.CreateBinding()\n    .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n    .AddSource(buttonPaste, nameof(buttonPaste.Click))\n    .AddTarget(textBox);\n\n// by disposing the binding every event subscription will be removed\nbinding.Dispose();\n```\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/7b0lFq).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_CommandBindingsCollection.htm\"\u003eCommandBindingsCollection\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIf you create your bindings by a `CommandBindingsCollection` (or add the created bindings to it), then all of the event subscriptions of every added binding can be removed at once when the collection is disposed.\n\n```cs\npublic class MyView : ViewBase\n{\n    private CommandBindingsCollection bindings = new CommandBindingsCollection();\n\n    private void InitializeView()\n    {\n        bindings.Add(MyCommands.PasteCommand)\n            .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n            .AddSource(buttonPaste, nameof(buttonPaste.Click))\n            .AddTarget(textBox);\n        // [...] more bindings\n    }\n\n    protected override void Dispose(bool disposing)\n    {\n        if (disposing)\n            bindings.Dispose(); // releases all of the event subscriptions of every added binding\n        base.Dispose(disposing);\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommandState.htm\"\u003eICommandState\u003c/a\u003e\u003c/code\u003e interface\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nAn [`ICommand`][ICommand] instance is stateless by itself. However, the created [`ICommandBinding`][ICommandBinding] has a `State` property, which is an [`ICommandState`][ICommandState] instance containing any arbitrary dynamic properties of the binding. Actually you can treat this object as a `dynamic` instance and add any properties you want. It has one predefined property, `Enabled`, which can be used to enable or disable the execution of the command.\n\n```cs\n// The command state can be pre-created and passed to the binding creation\nvar pasteCommandState = new CommandState { Enabled = false };\n\n// passing the state object when creating the binding\nvar pasteBinding = bindings.Add(MyCommands.PasteCommand, pasteCommandState)\n    .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n    .AddSource(buttonPaste, nameof(buttonPaste.Click))\n    .AddTarget(textBox);\n\n// ...\n\n// enabling the command\npasteCommandState.Enabled = true;\n// or:\npasteBinding.State.Enabled = true;\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCommand Enabled State - poll vs. push ways\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nAs you could see in the previous example the `Enabled` state of the command can set explicitly (push) any time via the [`ICommandState`][ICommandState] object.\n\nOn the other hand, it is possible to subscribe the `ICommandBinding.Executing` event, which is raised when a command is about to be executed. By this event the binding instance checks the enabled status (poll) and allows the subscriber to change it.\n\n```cs\n// Handling the ICommandBinding.Executing event. Of course, it can be a command, too... how fancy :)\n\npublic static class MyCommands\n{\n    // [...]\n\n    // this time we define a SourceAwareCommand because we want to get the event data\n    public static readonly ICommand SetPasteEnabledCommand =\n        new SourceAwareCommand\u003cExecuteCommandEventArgs\u003e(OnSetPasteEnabledCommand);\n\n    private static void OnSetPasteEnabledCommand(ICommandSource\u003cExecuteCommandEventArgs\u003e sourceData)\n    {\n        // we set the enabled state based on the clipboard\n        sourceData.EventArgs.State.Enabled = Clipboard.ContainsText();\n    }\n}\n\n// ...\n\n// and the creation of the bindings:\n\n// the same as previously, except that we don't pass a pre-created state this time.\nvar pasteBinding = bindings.Add(MyCommands.PasteCommand)\n    .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n    .AddSource(buttonPaste, nameof(buttonPaste.Click))\n    .AddTarget(textBox);\n\n// A command binding to set the Enabled state of the Paste command on demand (poll). No targets this time.\nbindings.Add(MyCommands.SetPasteEnabledCommand)\n    .AddSource(pasteBinding, nameof(pasteBinding.Executing));\n```\n\nThe possible drawback of the polling way is that `Enabled` is set only in the moment when the command is executed. But if the sources can represent the disabled state (e.g. visual elements may turn gray), then the explicit way may provide a better visual feedback. Just go on with reading...\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommandStateUpdater.htm\"\u003eICommandStateUpdater\u003c/a\u003e\u003c/code\u003e interface\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nAn [`ICommandState`][ICommandState] can store not just the predefined `Enabled` state but also any other data. If these states can be rendered meaningfully by the command sources (for example, when `Enabled` is false, then a source button or menu item can be disabled), then an `ICommandStateUpdater` can be used to apply the states to the sources. If the states are properties on the source, then the [`PropertyCommandStateUpdater`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_PropertyCommandStateUpdater.htm) can be added to the binding:\n\n```cs\n// we can pass a string-object dictionary to the constructor, or we can treat it as a dynamic object.\nvar pasteCommandState = new CommandState(new Dictionary\u003cstring, object\u003e\n{\n    { \"Enabled\", false }, // can be set also this way - must have a bool value\n    { \"Text\", \"Paste\" },\n    { \"HotKey\", Key.Control | Key.V },\n    { \"Icon\", Icons.PasteIcon },\n});\n\n// as now we add a state updater, the states will be immediately applied to the sources\nbindings.Add(MyCommands.PasteCommand, pasteCommandState)\n    .AddStateUpdater(PropertyCommandStateUpdater.Updater) // to sync back state properties to sources\n    .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n    .AddSource(buttonPaste, nameof(buttonPaste.Click))\n    .AddTarget(textBox);\n\n// This will enable all sources now (if they have an Enabled property):\npasteCommandState.Enabled = true;\n\n// We can set anything by casting the state to dynamic or via the AsDynamic property.\n// It is not a problem if a source does not have such a property. You can chain multiple updaters to\n// handle special cases. If an updater fails, the next one is tried (if any).\npasteCommandState.AsDynamic.ToolTip = \"Paste text from the Clipboard\";\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eParameterized Commands\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nIn WPF you can pass a parameter to a command, whose value is determined when the command is executed. KGy SOFT Libraries also have parameterized command support:\n\n```cs\nbindings.Add(MyCommands.ReplaceTextCommand)\n    .WithParameter(() =\u003e GetNewText()) // the delegate will be called when the command is executed\n    .AddSource(menuItemPaste, nameof(menuItemPaste.Click))\n    .AddSource(buttonPaste, nameof(buttonPaste.Click))\n    .AddTarget(textBox);\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e It is recommended to specify the parameter callback before adding any sources to avoid the possible issues if there is any chance that the source can be triggered before completing the initialization.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCommand Targets vs. Parameter\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nActually also the `AddTarget` method can accept a delegate, which is invoked just before executing the command.  The difference between targets and parameters is that whenever triggering the command the parameter value is evaluated only once but the `ICommand.Execute` method is invoked as many times as many targets are added to the binding (but at least once if there are no targets) using the same parameter value.\n\nBut if there are no multiple targets, then either a target or a parameter can be used interchangeably. Use whatever is more correct semantically. If the parameter/target can be determined when creating the binding (no callback is needed to determine its value), then it is probably rather a target than a parameter.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eProperty Binding\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nMost UI frameworks have some advanced property binding, supporting fancy things such as collections and paths. Though they can be perfectly used in most cases they can have also some drawbacks. For example, WPF data binding (similarly to other XAML based frameworks) can be used with `DependencyProperty` targets of `DependencyObject` instances only; and Windows Forms data binding works only for `IBindableComponent` implementations.\n\nFor environments without any binding support or for the aforementioned exceptional cases KGy SOFT's command binding offers a very simple one-way property binding by an internally predefined command exposed by the [`Command.CreatePropertyBinding`](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_ComponentModel_Command_CreatePropertyBinding.htm) and [`CommandBindingsCollection.AddPropertyBinding`](https://koszeggy.github.io/docs/corelibraries/html/Overload_KGySoft_ComponentModel_CommandBindingsCollection_AddPropertyBinding.htm) methods. The binding works for any sources, which implement the `INotifyPropertyChanged` interface, or, if they have a `\u003cPropertyName\u003eChanged` event for the property to bind. The target object can be anything as long as the target property can be set.\n\nIn the following example our view-model is a [`ModelBase`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ModelBase.htm) (see also [above](#business-objects)), which implements `INotifyPropertyChanged`.\n\n```cs\n// ViewModel:\npublic class MyViewModel : ModelBase // ModelBase implements INotifyPropertyChanged\n{\n    public string Text { get =\u003e Get\u003cstring\u003e(); set =\u003e Set(value); }\n}\n\n// View: assuming we have a ViewBase\u003cTDataContext\u003e class with DataContext and CommandBindings properties\npublic class MyView : ViewBase\u003cMyViewModel\u003e\n{\n    private void InitializeView()\n    {\n        CommandBindingsCollection bindings = base.CommandBindings;\n        MyViewModel viewModel = base.DataContext;\n\n        // [...] the usual bindings.Add(...) lines here\n\n        // Adding a simple property binding (uses a predefined command internally):\n        bindings.AddPropertyBinding(\n            viewModel, \"Text\", // source object and property name\n            \"Text\", textBox, labelTextBox); // target property name and target object(s)\n\n        // a formatting can be added if types (or just the values) of the properties should be different:\n        bindings.AddPropertyBinding(\n            viewModel, \"Text\", // source object and property name\n            \"BackColor\", // target property name\n            value =\u003e value == null ? Colors.Yellow : SystemColors.WindowColor, // string -\u003e Color conversion\n            textBox); // target object(s)\n    }\n}\n```\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e See the [KGySoft.ComponentModelDemo](https://github.com/koszeggy/KGySoft.ComponentModelDemo) repository to try command bindings in action\n\n[ICommand]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommand.htm\n[ICommandBinding]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommandBinding.htm\n[ICommandState]: https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_ComponentModel_ICommandState.htm\n\u003c/details\u003e\n\n### Performance Measurement\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eThe \u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Diagnostics_Profiler.htm\"\u003eProfiler\u003c/a\u003e\u003c/code\u003e class\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nYou can use the `Profiler` class to inject measurement sections as `using` blocks into your code base:\n\n```cs\nconst string category = \"Example\";\n\nusing (Profiler.Measure(category, \"DoBigTask\"))\n{\n    // ... code ...\n\n\t// measurement blocks can be nested\n    using (Profiler.Measure(category, \"DoSmallTask\"))\n    {\n        // ... more code ...\n    }\n}\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/BuuisW).\n\nThe number of hits, execution times (first, total, average) are tracked and can be obtained explicitly or you can let them to be dumped automatically into an .xml file.\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cProfilerResult\u003e\n  \u003citem Category = \"Example\" Operation=\"Main total\" NumberOfCalls=\"1\" FirstCall=\"00:00:00.5500736\" TotalTime=\"00:00:00.5500736\" AverageCallTime=\"00:00:00.5500736\" /\u003e\n  \u003citem Category = \"Example\" Operation=\"Main/1 iteration\" NumberOfCalls=\"10\" FirstCall=\"00:00:00.0555439\" TotalTime=\"00:00:00.5500554\" AverageCallTime=\"00:00:00.0550055\" /\u003e\n  \u003citem Category = \"Example\" Operation=\"DoSmallTask\" NumberOfCalls=\"60\" FirstCall=\"00:00:00.0005378\" TotalTime=\"00:00:00.0124114\" AverageCallTime=\"00:00:00.0002068\" /\u003e\n  \u003citem Category = \"Example\" Operation=\"DoBigTask\" NumberOfCalls=\"10\" FirstCall=\"00:00:00.0546513\" TotalTime=\"00:00:00.5455339\" AverageCallTime=\"00:00:00.0545533\" /\u003e\n\u003c/ProfilerResult\u003e\n```\n\nThe result .xml can be imported easily into Microsoft Excel:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Profiler results imported in Microsoft Excel\" src=\"https://user-images.githubusercontent.com/27336165/124354307-af603180-dc0b-11eb-83a6-edd474eb4919.png\"/\u003e\n  \u003cbr/\u003e\u003cem\u003eProfiler results imported in Microsoft Excel\u003c/em\u003e\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eThe \u003ccode\u003e\u003ca href=\"https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Diagnostics_PerformanceTest.htm\"\u003ePerformanceTest\u003c/a\u003e\u003c/code\u003e classes\u003c/strong\u003e\u003c/summary\u003e\u003cp/\u003e\n\nFor more direct operations you can use the [`PerformanceTest`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Diagnostics_PerformanceTest.htm) and [`PerformanceTest\u003cTResult\u003e`](https://koszeggy.github.io/docs/corelibraries/html/T_KGySoft_Diagnostics_PerformanceTest_1.htm) classes to measure operations with `void` and non-`void` return values, respectively.\n\n```cs\nnew PerformanceTest\n    {\n        TestName = \"System.Enum vs. KGySoft.CoreLibraries.Enum\u003cTEnum\u003e\",\n        Iterations = 1_000_000,\n        Repeat = 2\n    }\n    .AddCase(() =\u003e ConsoleColor.Black.ToString(), \"Enum.ToString\")\n    .AddCase(() =\u003e Enum\u003cConsoleColor\u003e.ToString(ConsoleColor.Black), \"Enum\u003cTEnum\u003e.ToString\")\n    .DoTest()\n    .DumpResults(Console.Out);\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/PCcVuD).\n\nThe result of the `DoTest` method can be processed either manually or can be dumped in any `TextWriter`. The example above dumps it on the console and produces a result similar to this one:\n\n```\n==[System.Enum vs. KGySoft.CoreLibraries.Enum\u003cTEnum\u003e Results]================================================\nIterations: 1,000,000\nWarming up: Yes\nTest cases: 2\nRepeats: 2\nCalling GC.Collect: Yes\nForced CPU Affinity: 2\nCases are sorted by time (quickest first)\n--------------------------------------------------\n1. Enum\u003cTEnum\u003e.ToString: average time: 26.60 ms\n  #1          29.40 ms   \u003c---- Worst\n  #2          23.80 ms   \u003c---- Best\n  Worst-Best difference: 5.60 ms (23.55%)\n2. Enum.ToString: average time: 460.78 ms (+434.18 ms / 1,732.36%)\n  #1         456.18 ms   \u003c---- Best\n  #2         465.37 ms   \u003c---- Worst\n  Worst-Best difference: 9.19 ms (2.01%)\n```\n\nIf you need to use parameterized tests you can simply derive the `PerformanceTestBase\u003cTDelegate, TResult\u003e` class. Override the `OnBeforeCase` method to reset the parameter for each test cases. For example, this is how you can use a prepared `Random` instance in a performance test:\n\n```cs\npublic class RandomizedPerformanceTest\u003cT\u003e : PerformanceTestBase\u003cFunc\u003cRandom, T\u003e, T\u003e\n{\n    private Random random;\n\n    protected override T Invoke(Func\u003cRandom, T\u003e del) =\u003e del.Invoke(random);\n\n    protected override void OnBeforeCase() =\u003e random = new Random(0); // resetting with a fix seed\n}\n```\n\n\u003e 💡 **Tip**\u003cp/\u003e\n\u003e Try also [online](https://dotnetfiddle.net/KNiZa7).\n\nAnd then a properly prepared `Random` instance will be an argument of your test cases:\n\n```cs\nnew RandomizedPerformanceTest\u003cstring\u003e { Iterations = 1_000_000 }\n    .AddCase(rnd =\u003e rnd.NextEnum\u003cConsoleColor\u003e().ToString(), \"Enum.ToString\")\n    .AddCase(rnd =\u003e Enum\u003cConsoleColor\u003e.ToString(rnd.NextEnum\u003cConsoleColor\u003e()), \"Enum\u003cTEnum\u003e.ToString\")\n    .DoTest()\n    .DumpResults(Console.Out);\n```\n\u003c/details\u003e\n\n## License\nKGy SOFT Core Libraries are under the [KGy SOFT License 1.0](https://github.com/koszeggy/KGySoft.CoreLibraries/blob/master/LICENSE), which is a permissive GPL-like license. It allows you to copy and redistribute the material in any medium or format for any purpose, even commercially. The only thing is not allowed is to distribute a modified material as yours: though you are free to change and re-use anything, do that by giving appropriate credit. See the [LICENSE](https://github.com/koszeggy/KGySoft.CoreLibraries/blob/master/LICENSE) file for details.\n\n---\n\nSee the complete KGy SOFT Core Libraries documentation with even more examples at the [docs](https://koszeggy.github.io/docs/corelibraries) site.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoszeggy%2FKGySoft.CoreLibraries","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoszeggy%2FKGySoft.CoreLibraries","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoszeggy%2FKGySoft.CoreLibraries/lists"}