RSCG – PropertyChangedSourceGenerator

RSCG – PropertyChangedSourceGenerator
 
 

name PropertyChangedSourceGenerator
nuget https://www.nuget.org/packages/PropertyChanged.SourceGenerator/
link https://github.com/canton7/PropertyChanged.SourceGenerator
author Antony Male

Generating PropertyChange to properties

 

This is how you can use PropertyChangedSourceGenerator .

The code that you start with is


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.8">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
	<PropertyGroup>
		<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
		<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
	</PropertyGroup>
</Project>


The code that you will use is


using PropChangeDemo;

Person person = new ();
person.FirstName = "Andrei";
Console.WriteLine (person.FirstName);


using PropertyChanged.SourceGenerator;
namespace PropChangeDemo;

partial class Person
{
    [Notify]    
    private string? _FirstName;
}


 

The code that is generated is

// <auto-generated>
//     Auto-generated by PropertyChanged.SourceGenerator 1.0.8.0
// </auto-generated>
namespace PropertyChanged.SourceGenerator
{
    /// <summary>
    /// Specifies the accessibility of a generated property getter
    /// </summary>
    internal enum Getter
    {
        Public = 6,
        ProtectedInternal = 5,
        Internal = 4,
        Protected = 3,
        PrivateProtected = 2,
        Private = 1,
    }

    /// <summary>
    /// Specifies the accessibility of a generated property getter
    /// </summary>
    internal enum Setter
    {
        Public = 6,
        ProtectedInternal = 5,
        Internal = 4,
        Protected = 3,
        PrivateProtected = 2,
        Private = 1,
    }

    /// <summary>
    /// Instruct PropertyChanged.SourceGenerator to generate a property which implements INPC using this backing field
    /// </summary>
    [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = false)]
    [global::System.Diagnostics.Conditional("DEBUG")]
    internal class NotifyAttribute : global::System.Attribute
    {
        /// <summary>
        /// Generate a property whose name is derived from the name of this field, with a public getter and setter
        /// </summary>
        public NotifyAttribute() { }

        /// <summary>
        /// Generate a property with the given name, and optionally the given getter and setter accessibilities
        /// </summary>
        /// <param name="name">Name of the generated property</param>
        /// <param name="get">Accessibility of the generated getter</param>
        /// <param name="set">Accessibility of the generated setter</param>
        public NotifyAttribute(string name, Getter get = Getter.Public, Setter set = Setter.Public) { }

        /// <summary>
        /// Generate a property whose name is derived from the name of this field, with the given getter and optionally setter accessibilities
        /// </summary>
        /// <param name="get">Accessibility of the generated getter</param>
        /// <param name="set">Accessibility of the generated setter</param>
        public NotifyAttribute(Getter get, Setter set = Setter.Public) { }

        /// <summary>
        /// Generate a property whose name is derived from the name of this field, with a public getter and the given setter accessibility
        /// </summary>
        /// <param name="set">Accessibility of the generated setter</param>
        public NotifyAttribute(Setter set) { }

        /// <summary>
        /// If <c>true</c>, the generated property will be <c>virtual</c>.
        /// </summary>
        public bool IsVirtual { get; set; }
    }

    /// <summary>
    /// Instruct PropertyChanged.SourceGenerator to also raise INPC notifications for the named properties whenever the property this is applied to changes
    /// </summary>
    [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = true)]
    [global::System.Diagnostics.Conditional("DEBUG")]
    internal class AlsoNotifyAttribute : global::System.Attribute
    {
        /// <summary>
        /// Raise INPC notifications for the given properties when the property generated for this backing field changes
        /// </summary>
        /// <param name="otherProperties">Other properties to raise INPC notifications for</param>
        public AlsoNotifyAttribute(params string[] otherProperties) { }
    }

    /// <summary>
    /// Instruct PropertyChanged.SourceGenerator to raise INPC notifications for this property whenever one of the named generated properties is changed
    /// </summary>
    [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = false)]
    [global::System.Diagnostics.Conditional("DEBUG")]
    internal class DependsOnAttribute : global::System.Attribute
    {
        /// <summary>
        /// Raise an INPC notification for this property whenever one of the named properties is changed
        /// </summary>
        /// <param name="dependsOn">Other properties this property depends on</param>
        public DependsOnAttribute(params string[] dependsOn) { }
    }

    /// <summary>
    /// Instruct PropertyChanged.SourceGenerator to assign true to this boolean property whenver any generated member changes
    /// </summary>
    [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = true)]
    [global::System.Diagnostics.Conditional("DEBUG")]
    internal class IsChangedAttribute : global::System.Attribute
    {
    }

    /// <summary>
    /// Specifies an attribute which will be added to the generated property for this backing field
    /// </summary>
    /// <remarks>
    /// The string passed to this attribute will be placed verbatim into the generated code. All types must therefore by fully-qualified.
    /// </remarks>
    [global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = true)]
    [global::System.Diagnostics.Conditional("DEBUG")]
    internal class PropertyAttributeAttribute : global::System.Attribute
    {
        /// <summary>
        /// Specify an attribute which iwll be added to the generated property for this backing field
        /// </summary>
        /// <param name="attribute">An attribute to place on the generated property</param>
        public PropertyAttributeAttribute(string attribute) { }
    }
}
// <auto-generated>
//     Auto-generated by PropertyChanged.SourceGenerator 1.0.8.0
// </auto-generated>
namespace PropertyChanged.SourceGenerator.Internal
{
    internal static class EventArgsCache
    {
        private static global::System.ComponentModel.PropertyChangedEventArgs _PropertyChanged_FirstName;
        public static global::System.ComponentModel.PropertyChangedEventArgs PropertyChanged_FirstName => _PropertyChanged_FirstName ??= new global::System.ComponentModel.PropertyChangedEventArgs(@"FirstName");
    }
}

// <auto-generated>
//     Auto-generated by PropertyChanged.SourceGenerator 1.0.8.0
// </auto-generated>
#nullable enable
namespace PropChangeDemo
{
    partial class Person : global::System.ComponentModel.INotifyPropertyChanged
    {
        /// <inheritdoc />
        public event global::System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;
        public string? FirstName
        {
            get => this._FirstName;
            set
            {
                if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(value, this._FirstName))
                {
                    this._FirstName = value;
                    this.OnPropertyChanged(global::PropertyChanged.SourceGenerator.Internal.EventArgsCache.PropertyChanged_FirstName);
                }
            }
        }
        /// <summary>
        /// Raises the PropertyChanged event
        /// </summary>
        /// <param name="eventArgs">The EventArgs to use to raise the event</param>
        protected virtual void OnPropertyChanged(global::System.ComponentModel.PropertyChangedEventArgs eventArgs)
        {
            this.PropertyChanged?.Invoke(this, eventArgs);
        }
    }
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/PropertyChangedSourceGenerator