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
Leave a Reply