LazyINotify 1.0.2

dotnet add package LazyINotify --version 1.0.2
                    
NuGet\Install-Package LazyINotify -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LazyINotify" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LazyINotify" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="LazyINotify" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LazyINotify --version 1.0.2
                    
#r "nuget: LazyINotify, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LazyINotify@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LazyINotify&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=LazyINotify&version=1.0.2
                    
Install as a Cake Tool

LazyINotify

An abstract class implementing the INotifyPropertyChanging and INotifyPropertyChanged interfaces from System.ComponentModel via specialized get/set accessors.

Namespace tree

LazyINotifyLib [root namespace]
│
├─ Miscellaneous [namespace] <-- Contains auxiliary parts and also an addition in the form of INotifyPropertyGetting interface
│  │
│  ├─ NewInstanceAsDefaultValueAttribute [class derived from Attribute]
│  │
│  ├─ ValueFormattingInstructor [delegate object?]
│  │
│  │
│  ├─ INotifyPropertyGetting [interface]
│  │
│  ├─ PropertyGettingEventHandler [delegate void]
│  │
│  └─ PropertyGettingEventArgs [class derived from EventArgs]
│
└─ LazyINotify [abstract class] <-- Main class

Example of basic usage

using LazyINotifyLib;
using LazyINotifyLib.Miscellaneous; // For NewInstanceAsDefaultValueAttribute
using System.ComponentModel; // For DefaultValueAttribute

// ...

public class ApplicationViewModelClass : LazyINotify
{
    // Default value is not set
    public string? FirstProperty { get => NotifyGet(); set => NotifySet(value); }


    // Default value for regular types
    [DefaultValue("Default value for the second property")] // Attribute from System.ComponentModel namespace
    public string SecondProperty { get => NotifyGet()!; set => NotifySet(value); }


    // Default value via Activator.CreateInstance()
    [NewInstanceAsDefaultValue(["First argument of the constructor", 2.0])] // Attribute from LazyINotifyLib.Miscellaneous namespace
    public DummyClass ThirdProperty { get => NotifyGet()!; set => NotifySet(value); }

    public class DummyClass(string FirstConstructorArgument, double SecondConstructorArgument)
    {
        public string FirstDummyProperty { get; } = FirstConstructorArgument;
        public double SecondDummyProperty { get; } = SecondConstructorArgument;
    }
}

NewInstanceAsDefaultValueAttribute is Attribute class located in the LazyINotifyLib.Miscellaneous namespace.

The target value type of NotifyGet() and NotifySet() methods is dynamic to avoid needless type casts. Both methods use [CallerMemberName] attribute for the string PropertyName = "" argument to identify target property name without constantly specifying it.

  • NotifySet() invokes PropertyChanging and PropertyChanged events.
  • NotifyGet() invokes additional PropertyGetting event added from LazyINotifyLib.Miscellaneous namespace.

    The PropertyGetting event is a small addition to justify the name of the NotifyGet() method (And just why not).

ValueFormattingInstructor usage

NotifyGet() and NotifySet() methods also accepts ValueFormattingInstructor delegate as an argument. This delegate is located in the LazyINotifyLib.Miscellaneous namespace. It allows to change the value through a specified method that must return an object?-type value. Alternatively, it can be used as a custom action for additional manipulations before getting/setting a value based on the property name and value to get/set.

Very basic example of said usages:

using LazyINotifyLib;
using System.ComponentModel; // For DefaultValueAttribute

// ...

public class ApplicationViewModelClass : LazyINotify
{
    [DefaultValue(10.0)] // Testing property
    public double NumberProperty { get => NotifyGet(ValueFormatting: NumberAcquiringNotify); set => NotifySet(value, ValueFormatting: NumberRangeAssertionOnSet); }



    private static object? NumberRangeAssertionOnSet(string PropertyName, object? Value)
    {
        if (Value is double Number)
        {
            if (Number > 50)
            {
                Console.WriteLine($"[{DateTime.Now}] Excessive value '{Number}' received for \"{PropertyName}\".");
                Number = 50;
            }
            else if (Number < 0)
            {
                Console.WriteLine($"[{DateTime.Now}] Insufficient value '{Number}' received for \"{PropertyName}\".");
                Number = 0;
            }

            Value = Number;
        }

        return Value; // -> actually store by LazyINotify.NotifySet()
    }

    private static object? NumberAcquiringNotify(string PropertyName, object? Value)
    {
        Console.WriteLine($"[{DateTime.Now}] The value '{Value}' is returned from the \"{PropertyName}\" property.");
        
        return Value; // -> return from LazyINotify.NotifyGet()
    }
}

PropertyAcknowledgementLevel usage

LazyINotify class also contains a protected virtual property PropertyAcknowledgementLevel of type System.Reflection.BindingFlags. This property determines which access level properties should be accessible in NotifyGet / NotifySet. Base value is BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance (public / private / protected access levels).

Example of overriding with permission for only public properties (BindingFlags.Public | BindingFlags.Instance):

using LazyINotifyLib;
using System.Reflection; // For BindingFlags
using System.ComponentModel; // For DefaultValueAttribute

// ...

public class ApplicationViewModelClass : LazyINotify
{
    // Overriding with permission for only `public` properties
    protected override BindingFlags PropertyAcknowledgementLevel => BindingFlags.Public | BindingFlags.Instance;


    [DefaultValue("Default string 1 (public)")] // public property
    public string PublicStringProperty { get => NotifyGet(); set => NotifySet(value); }

    [DefaultValue("Default string 2 (private)")] // private property
    private string PrivateStringProperty { get => NotifyGet(); set => NotifySet(value); }


    public void ShowAllData()
    {
        // [✓] This will work fine
        Console.WriteLine($"Public string is: \"{PublicStringProperty}\"");

        // [🞩] This will throw an ArgumentException
        Console.WriteLine($"Private string is: \"{PrivateStringProperty}\"");
    }
}
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Added XML annotations