{"id":15011555,"url":"https://github.com/x39/x39.sourcegenerators.property","last_synced_at":"2025-04-12T03:43:54.334Z","repository":{"id":226316921,"uuid":"768361265","full_name":"X39/X39.SourceGenerators.Property","owner":"X39","description":"source generator that generates properties for a given class","archived":false,"fork":false,"pushed_at":"2024-12-20T14:42:29.000Z","size":147,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T23:23:27.771Z","etag":null,"topics":["csharp","dotnet","library","nuget","nuget-package","source-generator"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/X39.SourceGenerators.Property","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/X39.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2024-03-07T00:02:10.000Z","updated_at":"2025-03-17T10:42:57.000Z","dependencies_parsed_at":"2024-03-22T17:57:55.110Z","dependency_job_id":"34779e4f-f4c3-4e7b-85f6-2582ec3f7a70","html_url":"https://github.com/X39/X39.SourceGenerators.Property","commit_stats":{"total_commits":24,"total_committers":2,"mean_commits":12.0,"dds":0.04166666666666663,"last_synced_commit":"e614d97c7c20305039b2059ef74b01d8553fbe39"},"previous_names":["x39/x39.sourcegenerators.property"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.SourceGenerators.Property","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.SourceGenerators.Property/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.SourceGenerators.Property/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.SourceGenerators.Property/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/X39","download_url":"https://codeload.github.com/X39/X39.SourceGenerators.Property/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248514211,"owners_count":21116899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["csharp","dotnet","library","nuget","nuget-package","source-generator"],"created_at":"2024-09-24T19:41:14.777Z","updated_at":"2025-04-12T03:43:54.314Z","avatar_url":"https://github.com/X39.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- TOC --\u003e\n* [X39.SourceGenerators.Property](#x39sourcegeneratorsproperty)\n* [Quick Start](#quick-start)\n* [Common fixes with source generators](#common-fixes-with-source-generators)\n  * [The Source-Generator is not working (After installing the package; After Building)](#the-source-generator-is-not-working-after-installing-the-package-after-building)\n  * [`dotnet build` errors that it cannot find the generated output](#dotnet-build-errors-that-it-cannot-find-the-generated-output)\n  * [Rider does not recognize the source generator](#rider-does-not-recognize-the-source-generator)\n* [When and how are properties generated?](#when-and-how-are-properties-generated)\n* [Attributes](#attributes)\n  * [`GeneratePropertiesAttribute` (class | field)](#generatepropertiesattribute-class--field)\n    * [On the class](#on-the-class)\n    * [On the field](#on-the-field)\n  * [`DisableAttributeTakeoverAttribute` (class | field)](#disableattributetakeoverattribute-class--field)\n    * [On the class](#on-the-class-1)\n    * [On the field](#on-the-field-1)\n  * [`NoPropertyAttribute` (field)](#nopropertyattribute-field)\n    * [On the field](#on-the-field-2)\n  * [`PropertyAttributeAttribute` (class | field)](#propertyattributeattribute-class--field)\n    * [On the class](#on-the-class-2)\n    * [On the field (inherit: false)](#on-the-field-inherit-false)\n    * [On the field (inherit: true)](#on-the-field-inherit-true)\n  * [`NotifyPropertyChangedAttribute` (class | field)](#notifypropertychangedattribute-class--field)\n    * [On the class with true](#on-the-class-with-true)\n    * [On the class with false](#on-the-class-with-false)\n    * [On the field with true](#on-the-field-with-true)\n    * [On the field with false](#on-the-field-with-false)\n  * [`NotifyPropertyChangingAttribute` (class | field)](#notifypropertychangingattribute-class--field)\n    * [On the class with true](#on-the-class-with-true-1)\n    * [On the class with false](#on-the-class-with-false-1)\n    * [On the field with true](#on-the-field-with-true-1)\n    * [On the field with false](#on-the-field-with-false-1)\n  * [`PropertyNameAttribute` (field)](#propertynameattribute-field)\n    * [On the field](#on-the-field-3)\n  * [`ValidationStrategyAttribute` (class | field)](#validationstrategyattribute-class--field)\n    * [Supported Validations](#supported-validations)\n    * [Available Strategies](#available-strategies)\n    * [On the class  (`EValidationStrategy.Exception`)](#on-the-class-evalidationstrategyexception)\n    * [On the field (`EValidationStrategy.Exception`)](#on-the-field-evalidationstrategyexception)\n    * [On the class  (`EValidationStrategy.Rollback`)](#on-the-class-evalidationstrategyrollback)\n    * [On the class  (`EValidationStrategy.Ignore`)](#on-the-class-evalidationstrategyignore)\n  * [`PropertyEncapsulationAttribute` (field)](#propertyencapsulationattribute-field)\n    * [On the field](#on-the-field-4)\n  * [`VirtualPropertyAttribute` (field)](#virtualpropertyattribute-field)\n    * [On the field](#on-the-field-5)\n  * [`EqualityCheckAttribute` (class | field)](#equalitycheckattribute-class--field)\n    * [Supported Equality Modes](#supported-equality-modes)\n    * [On the class  (`EEqualityCheckMode.Default`)](#on-the-class-eequalitycheckmodedefault)\n    * [On the class  (`EEqualityCheckMode.Custom`)](#on-the-class-eequalitycheckmodecustom)\n    * [On the class  (`EEqualityCheckMode.None`)](#on-the-class-eequalitycheckmodenone)\n    * [On the field  (`EEqualityCheckMode.Default`)](#on-the-field-eequalitycheckmodedefault)\n  * [`GuardAttribute` (field)](#guardattribute-field)\n    * [On the field](#on-the-field-6)\n* [Project Notes](#project-notes)\n  * [Building](#building)\n  * [Test coverage](#test-coverage)\n  * [Contributing](#contributing)\n    * [Code of Conduct](#code-of-conduct)\n    * [Contributors Agreement](#contributors-agreement)\n  * [License](#license)\n\u003c!-- TOC --\u003e\n\n# X39.SourceGenerators.Property\n\nThis library adds a source generator that generates properties for a given class.\n\nBy default, any property put onto a field will also be taken over to the generated property.\nYou can use the [`DisableAttributeTakeoverAttribute`](#disableattributetakeoverattribute-class--field) to disable this\nbehavior.\n\nTo enable the source generator for a class, you have to add one of the class-level attributes to the class (\nSee [Attributes](#Attributes)).\n\n# Quick Start\n\nAdd the nuget package to your project.\nAfter that, make the classes you want to generate properties for partial and add corresponding attributes to the class,\neg.:\n\n```csharp\nusing X39.SourceGenerators.Property;\n\n[NotifyPropertyChanged]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n```\n\nThis will generate a partial class with the following content:\n\n```csharp\n#nullable enable\npublic partial class MyClass\n    : System.ComponentModel.INotifyPropertyChanged\n{\n    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n# Common fixes with source generators\n\n## The Source-Generator is not working (After installing the package; After Building)\n\nAfter installing the package,\ncheck whether the build output contains a `CS9057` warning.\nIf it does, your compiler is not updated enough to support this source generator.\nInstall the latest .NET SDK to fix this.\n\n## `dotnet build` errors that it cannot find the generated output\n\nThe dotnet build server may have something cached.\nRun `dotnet build-server shutdown` to restart the build server.\n\n## Rider does not recognize the source generator\n\nThere might be multiple issues here:\n\n- You may have to restart Rider after installing the package to make the source generator work.\n- Make sure Roslyn Analyzers are enabled in the settings.\n  Search for \"Roslyn\" in the settings and enable all Roslyn related checkboxes related to building.\n\n# When and how are properties generated?\n\nThe properties are generated when one of the (Attributes)[#Attributes] is placed on the class or field.\nThe source generator will then generate a partial class with the same name as the original class and add the properties\nto it.\n\n# What about documentation?\n\nDocumenting the generated properties is as simple as documenting the field.\nLike, really, just document the field and the documentation will be copied\nover to the property. No need to break workflow in any way.\n\n### Propety Name\n\nThe property **name** will be the name of the field with the first letter capitalized and an optional underscore\nremoved.\nAdditionally, if the field is suffixed with `Field`, the suffix will be removed too.\nSee (`PropertyNameAttribute`)[#PropertyNameAttribute] to customize the property name.\n\nFor a more \"example driven\" approach to this explanation, see the following table:\n\n| Field Name  | Property Name |\n|-------------|---------------|\n| `_abc`      | `Abc`         |\n| `_abcField` | `Abc`         |\n| `abc`       | `Abc`         |\n| `__abc`     | `_abc`        |\n| `_abc_`     | `Abc_`        |\n\n### `readonly` handling\nIf the field is `readonly`, the property will be `readonly` too.\nWhat this means is that the property will be created\nwith a normal `get` getter and a `init` setter.\n\nSee [`SetterAttribute`](#SetterAttribute) to customize whether the setter\nshould be generated at all.\n\nSimilarly, see [`GetterAttribute`](#GetterAttribute) to customize whether the getter\nshould be generated at all.\n\n\n# Attributes\n\nSome attributes are placeable on either the class or field.\nIf the attribute is placed on the class, the attribute will be taken as a default for all fields.\nThis also implies that the field attributes always take precedence over the class attributes.\n\n## `GeneratePropertiesAttribute` (class | field)\n\nThis attribute will make the source generator generate properties if no other attribute is desired.\n\n### On the class\n\n```csharp\n// User-Code\n[GenerateProperties]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [GenerateProperties]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `GetterAttribute` (field)\n\nThis attribute allows to customize the getter of a property.\nIt has two modes available:\n- `EGetterMode.Default`\n  This mode will leave the variant of the getter to the source generator.\n  *This is the default mode.*\n- `EGetterMode.None`\n  This mode will not generate a getter for the property.\n\nIt cannot be placed on the class.\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [Getter(EGetterMode.None)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `SetterAttribute` (field)\n\nThis attribute allows to customize the setter of a property.\nIt has four modes available:\n- `ESetterMode.Default`\n  This mode will leave the variant of the setter to the source generator.\n  *This is the default mode.*\n- `ESetterMode.Set`\n  This mode will generate a setter for the property.\n  **Warning:** Using this mode on a `readonly` field will result in a compiler error.\n- `ESetterMode.Init`\n  This mode will generate an `init` setter for the property.\n  Init setters will not generate equality checks or notify property changing/-ed events.\n- `ESetterMode.None`\n  This mode will not generate a setter for the property.\n\nIt cannot be placed on the class.\n\n### On the field (`ESetterMode.Default`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [Setter(ESetterMode.Default)]\n    private int _myProperty1;\n    \n    [Setter(ESetterMode.Default)]\n    private readonly int _myProperty2;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty1\n    {\n        get =\u003e _myProperty1;\n        set\n        {\n            if (_myProperty1 == value)\n                return;\n            _myProperty1 = value;\n        }\n    }\n    \n    public int MyProperty2\n    {\n        get =\u003e _myProperty2;\n        init\n        {\n            _myProperty2 = value;\n        }\n    }\n}\n```\n\n### On the field (`ESetterMode.Set`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [Setter(ESetterMode.Set)]\n    private int _myProperty1;\n    \n    [Setter(ESetterMode.Set)]\n    private readonly int _myProperty2;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty1\n    {\n        get =\u003e _myProperty1;\n        set\n        {\n            if (_myProperty1 == value)\n                return;\n            _myProperty1 = value;\n        }\n    }\n    \n    public int MyProperty2\n    {\n        get =\u003e _myProperty2;\n        set\n        {\n            if (_myProperty2 == value)\n                return;\n            _myProperty2 = value;\n        }\n    }\n}\n```\n\n### On the field (`ESetterMode.Init`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [Setter(ESetterMode.Init)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        init\n        {\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field (`ESetterMode.None`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [Setter(ESetterMode.None)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n    }\n}\n```\n\n## `NotifyOnAttribute` (property)\n\nThis attribute will cause the source generator to generate additional change notifications for the property\nattached, if the named property is changing (and managed by the source generator).\n\n### On the property\n\n```csharp\n// User-Code\n[NotifyPropertyChanging(true)]\n[NotifyPropertyChanged(true)]\npublic partial class MyClass\n{\n    private int _myProperty;\n    [NotifyOn(nameof(MyProperty))]\n    public int Indicection =\u003e _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n    : System.ComponentModel.INotifyPropertyChanged\n{\n    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            this.PropertyChanging?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n            this.PropertyChanging?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(Indirection)));\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(Indirection)));\n        }\n    }\n}\n```\n\n## `DisableAttributeTakeoverAttribute` (class | field)\n\nThis attribute will make the source generator not take over any attributes from the field to the property.\nIf the attribute is placed on the class, the source generator will not take over any attributes from any field.\nIf the attribute is placed on the field, the source generator will not take over any attributes from the specific field\nonly.\n\nBy default, the source generator will take over any attribute from the field to the property.\n\n### On the class\n\n```csharp\n// User-Code\n[DisableAttributeTakeover]\npublic partial class MyClass\n{\n    [MyFancyAttribute]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    [MyFancyAttribute]\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [DisableAttributeTakeover]\n    [MyFancyAttribute]\n    private int _myProperty1;\n    \n    [MyFancyAttribute]\n    private int _myProperty2;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty1\n    {\n        get =\u003e _myProperty1;\n        set\n        {\n            if (_myProperty1 == value)\n                return;\n            _myProperty1 = value;\n        }\n    }\n    \n    [MyFancyAttribute]\n    public int MyProperty2\n    {\n        get =\u003e _myProperty2;\n        set\n        {\n            if (_myProperty2 == value)\n                return;\n            _myProperty2 = value;\n        }\n    }\n}\n```\n\n## `NoPropertyAttribute` (field)\n\nThis attribute will make the source generator not generate a property for the field.\nIt cannot be placed on the class.\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    private int _myProperty1;\n    \n    [NoProperty]\n    private int _myProperty2;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty1\n    {\n        get =\u003e _myProperty1;\n        set\n        {\n            if (_myProperty1 == value)\n                return;\n            _myProperty1 = value;\n        }\n    }\n}\n```\n\n## `PropertyAttributeAttribute` (class | field)\n\nThis attribute will make the source generator add the given attribute to the generated property.\nIf applied to the class, the attribute will be added to all properties.\nA field attribute by default takes precedence over the class attribute, using the `inherit` parameter, the field\nattribute can be instructed to inherit the class attribute if desired.\n\n### On the class\n\n```csharp\n// User-Code\n[PropertyAttribute(\"Required\")]\n[PropertyAttribute(\"[Required]\")]\n[PropertyAttribute(\"[Required, Range(0, 10)]\")]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    [Required]\n    [Required]\n    [Required, Range(0, 10)]\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field (inherit: false)\n\n```csharp\n// User-Code\n[PropertyAttribute(\"MaxLenght(10)\")]\npublic partial class MyClass\n{\n    [PropertyAttribute(\"Required\")]\n    [PropertyAttribute(\"[Required]\")]\n    [PropertyAttribute(\"[Required, Range(0, 10)]\")]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    [Required]\n    [Required]\n    [Required, Range(0, 10)]\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field (inherit: true)\n\n```csharp\n// User-Code\n[PropertyAttribute(\"MaxLenght(10)\")]\npublic partial class MyClass\n{\n    [PropertyAttribute(\"Required\", inherit: true)]\n    [PropertyAttribute(\"Range(0, 10)\"]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    [Required]\n    [MaxLenght(10)]\n    [Range(0, 10)]\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `NotifyPropertyChangedAttribute` (class | field)\n\nThis attribute will make the source generator add a `PropertyChanged` event call to the setter of the property.\nIf the attribute is placed on the class and the parameter is set to `true` (default: `true`),\nthe source generator will implement the `INotifyPropertyChanged` interface on the class.\n\n### On the class with true\n\n```csharp\n// User-Code\n[NotifyPropertyChanged] // or [NotifyPropertyChanged(true)]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n    : System.ComponentModel.INotifyPropertyChanged\n{\n    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n### On the class with false\n\n```csharp\n// User-Code\n[NotifyPropertyChanged(false)]\npublic partial class MyClass : INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler? PropertyChanged;\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field with true\n\n```csharp\n// User-Code\npublic partial class MyClass : INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler? PropertyChanged;\n    [NotifyPropertyChanged] // or [NotifyPropertyChanged(true)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n### On the field with false\n\n```csharp\n// User-Code\npublic partial class MyClass : INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler? PropertyChanged;\n    [NotifyPropertyChanged(false)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `NotifyPropertyChangingAttribute` (class | field)\n\nThis attribute will make the source generator add a `PropertyChanging` event call to the setter of the property.\nIf the attribute is placed on the class and the parameter is set to `true` (default: `true`),\nthe source generator will implement the `INotifyPropertyChanging` interface on the class.\n\n### On the class with true\n\n```csharp\n// User-Code\n[NotifyPropertyChanging] // or [NotifyPropertyChanging(true)]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n    : System.ComponentModel.INotifyPropertyChanging\n{\n    public event System.ComponentModel.PropertyChangingEventHandler? PropertyChanging;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n            this.PropertyChanging?.Invoke(this, new System.ComponentModel.PropertyChangingEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n### On the class with false\n\n```csharp\n// User-Code\n[NotifyPropertyChanging(false)]\npublic partial class MyClass : INotifyPropertyChanging\n{\n    public event PropertyChangingEventHandler? PropertyChanging;\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field with true\n\n```csharp\n// User-Code\npublic partial class MyClass : INotifyPropertyChanging\n{\n    public event PropertyChangingEventHandler? PropertyChanging;\n    [NotifyPropertyChanging] // or [NotifyPropertyChanging(true)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n            this.PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n### On the field with false\n\n```csharp\n// User-Code\npublic partial class MyClass : INotifyPropertyChanging\n{\n    public event PropertyChangingEventHandler? PropertyChanging;\n    [NotifyPropertyChanging(false)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `PropertyNameAttribute` (field)\n\nThis attribute will make the source generator use the given name as the property name.\nIt cannot be placed on the class.\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [PropertyName(\"MyProperty\")]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `ValidationStrategyAttribute` (class | field)\n\nThe validation strategy attribute is used to define how additional, validating properties should be handled, when\nthe validation fails.\n\n### Supported Validations\n\n- `System.ComponentModel.DataAnnotations.RangeAttribute`\n- `System.ComponentModel.DataAnnotations.MaxLengthAttribute`\n- [`GuardAttribute`](#guardattribute-field)\n\n### Available Strategies\n\n- `EValidationStrategy.Exception`\n  This strategy will throw an `ArgumentException` when the validation fails.\n  *This is the default strategy.*\n- `EValidationStrategy.Rollback`\n  This strategy will behave like the `Ignore` strategy, unless `NotifyPropertyChanged` is also present.\n  If the `NotifyPropertyChanged` attribute is present, the event will be raised with no value change.\n- `EValidationStrategy.Ignore`\n  This strategy will ignore the validation and exit the setter without changing the value.\n\n### On the class  (`EValidationStrategy.Exception`)\n\n```csharp\n// User-Code\n[ValidationStrategy(EValidationStrategy.Exception)]\npublic partial class MyClass\n{\n    [Range(0, 10)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            if (value \u003c 0 || value \u003e 10)\n                throw new System.ArgumentException(\"Validation of Field failed: Value must be between 0 and 10\", nameof(value));\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field (`EValidationStrategy.Exception`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [ValidationStrategy(EValidationStrategy.Exception)]\n    [Range(0, 10)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            if (value \u003c 0 || value \u003e 10)\n                throw new System.ArgumentException(\"Validation of Field failed: Value must be between 0 and 10\", nameof(value));\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the class  (`EValidationStrategy.Rollback`)\n\n```csharp\n// User-Code\n[ValidationStrategy(EValidationStrategy.Rollback)]\n[NofityPropertyChanged(true)]\npublic partial class MyClass\n{\n    [Range(0, 10)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            if (value \u003c 0 || value \u003e 10)\n            {\n                this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n                return;\n            }\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n### On the class  (`EValidationStrategy.Ignore`)\n\n```csharp\n// User-Code\n[ValidationStrategy(EValidationStrategy.Ignore)]\n[NofityPropertyChanged(true)]\npublic partial class MyClass\n{\n    [Range(0, 10)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            if (value \u003c 0 || value \u003e 10)\n                return;\n            _myProperty = value;\n            this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(MyProperty)));\n        }\n    }\n}\n```\n\n## `PropertyEncapsulationAttribute` (field)\n\nThis attribute will make the source generator encapsulate the property with the given access modifier.\nIt cannot be placed on the class.\n\nPossible values are:\n\n- `EPropertyEncapsulation.Public`\n- `EPropertyEncapsulation.Protected`\n- `EPropertyEncapsulation.Internal`\n- `EPropertyEncapsulation.Private`\n- `EPropertyEncapsulation.ProtectedInternal`\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [PropertyEncapsulation(EPropertyEncapsulation.Protected)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    protected int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `VirtualPropertyAttribute` (field)\n\nThis attribute will make the source generator generate a virtual property.\nIt cannot be placed on the class.\n\n### On the field\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [VirtualProperty]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public virtual int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `EqualityCheckAttribute` (class | field)\n\nThis attribute will change how or if the equality check is performed.\n\n### Supported Equality Modes\n\n- `EEqualityCheckMode.Default`\n  This mode will use the default equality check, using `==` for primitive types and `object.Equals` for non-primitive\n  types.\n  *This is the default mode.*\n- `EEqualityCheckMode.Custom`\n  This mode will use the given method to check for equality.\n  The method must be a method with the signature `bool MethodName(T oldValue, T newValue)`.\n  The method must be accessible from the generated code.\n  If custom equality check is used, the `Custom` argument must be set to the name of the method or the generated code\n  will fall back to the default equality check.\n- `EEqualityCheckMode.None`\n  This mode will not generate an equality check.\n\n### On the class  (`EEqualityCheckMode.Default`)\n\n```csharp\n// User-Code\n[EqualityCheck(EEqualityCheckMode.Default)]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the class  (`EEqualityCheckMode.Custom`)\n\n```csharp\n// User-Code\n[EqualityCheck(EEqualityCheckMode.Custom, \"MyEqualityCheck\")]\npublic partial class MyClass\n{\n    private static bool MyEqualityCheck(int left, int right) =\u003e left == right;\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (MyEqualityCheck(_myProperty, value))\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the class  (`EEqualityCheckMode.None`)\n\n```csharp\n// User-Code\n[EqualityCheck(EEqualityCheckMode.None)]\npublic partial class MyClass\n{\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            _myProperty = value;\n        }\n    }\n}\n```\n\n### On the field  (`EEqualityCheckMode.Default`)\n\n```csharp\n// User-Code\npublic partial class MyClass\n{\n    [EqualityCheck(EEqualityCheckMode.Default)]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (_myProperty == value)\n                return;\n            _myProperty = value;\n        }\n    }\n}\n```\n\n## `GuardAttribute` (field)\n\nThe guard attribute allows to make the source generator use custom validation methods to validate the property.\nSee the [`ValidationStrategyAttribute`](#validationstrategyattribute-class--field) for more information on how to change\nvalidation\nhandling.\nIt cannot be placed on the class.\n\nThe guard method must be a method with the signature `bool MethodName(T oldValue, T newValue)` and has to be accessible\nfrom the generated code.\nMultiple guards may be used with all of them being checked in the order they are placed on the field.\n\n### On the field\n\n```csharp\n// User-Code\nnamespace SomethingFancy\n{\n    public static GuardMethods\n    {\n        public static bool MyGuard(int oldValue, int newValue) =\u003e newValue \u003e 0;\n    }\n}\npublic partial class MyClass\n{\n    [Guard(\"MyGuard\", className: \"SomethingFancy.GuardMethods\")]\n    private int _myProperty;\n}\n\n// Generated-Code\npublic partial class MyClass\n{\n    public int MyProperty\n    {\n        get =\u003e _myProperty;\n        set\n        {\n            if (!SomethingFancy.GuardMethods.MyGuard(_myProperty, value))\n                throw new System.ArgumentException(\"Validation of Field failed: Guard method SomethingFancy.GuardMethods.MyGuard failed\", nameof(value));\n            _myProperty = value;\n        }\n    }\n}\n```\n\n# Project Notes\n\nThis project is part of my personal utility libraries i use in my projects.\nThe following few paragraphs are meant to give you an overview of the project and how you can contribute to it.\n\n## Building\n\nThis project uses GitHub Actions for continuous integration. The workflow is defined in `.github/workflows/main.yml`. It\nincludes steps for restoring dependencies, building the project, and publishing a NuGet package.\n\n## Test coverage\n\nThis project is covered by unit tests for the generator only.\nThis means that the generated code is not yet tested.\n\n## Contributing\n\nContributions are welcome!\nPlease submit a pull request or create a discussion to discuss any changes you wish to make.\n\n### Code of Conduct\n\nBe excellent to each other.\n\n### Contributors Agreement\n\nFirst of all, thank you for your interest in contributing to this project!\nPlease add yourself to the list of contributors in the [CONTRIBUTORS](CONTRIBUTORS.md) file when submitting your\nfirst pull request.\nAlso, please always add the following to your pull request:\n\n```\nBy contributing to this project, you agree to the following terms:\n- You grant me and any other person who receives a copy of this project the right to use your contribution under the\n  terms of the GNU Lesser General Public License v3.0.\n- You grant me and any other person who receives a copy of this project the right to relicense your contribution under\n  any other license.\n- You grant me and any other person who receives a copy of this project the right to change your contribution.\n- You waive your right to your contribution and transfer all rights to me and every user of this project.\n- You agree that your contribution is free of any third-party rights.\n- You agree that your contribution is given without any compensation.\n- You agree that I may remove your contribution at any time for any reason.\n- You confirm that you have the right to grant the above rights and that you are not violating any third-party rights\n  by granting these rights.\n- You confirm that your contribution is not subject to any license agreement or other agreement or obligation, which\n  conflicts with the above terms.\n```\n\nThis is necessary to ensure that this project can be licensed under the GNU Lesser General Public License v3.0 and\nthat a license change is possible in the future if necessary (e.g., to a more permissive license).\nIt also ensures that I can remove your contribution if necessary (e.g., because it violates third-party rights) and\nthat I can change your contribution if necessary (e.g., to fix a typo, change implementation details, or improve\nperformance).\nIt also shields me and every user of this project from any liability regarding your contribution by deflecting any\npotential liability caused by your contribution to you (e.g., if your contribution violates the rights of your\nemployer).\nFeel free to discuss this agreement in the discussions section of this repository, i am open to changes here (as long as\nthey do not open me or any other user of this project to any liability due to a **malicious contribution**).\n\n## License\n\nThis project is licensed under the GNU Lesser General Public License v3.0. See the [LICENSE](LICENSE) file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx39%2Fx39.sourcegenerators.property","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fx39%2Fx39.sourcegenerators.property","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx39%2Fx39.sourcegenerators.property/lists"}