August 26, 2021

Exposing C# Events using Reactive Extensions

There is a way to convert existing C# events to an IObservable<>. There is a good article here on this

public class SimpleEventSource
{
  public event EventHandler<MyEventArgs> SimpleEvent;
     
  // Normally this would be private (event is triggered internally) 
  // but for test purposes we make it public
  public void FireSimpleEvent(MyEvent myevent)
  {
    EventHandler<MyEventArgs> tmp = SimpleEvent;
    if (tmp != null)
    {
      tmp(this, new MyEventArgs(myEvent));
    }
  }   
 
  // This returns an IObservable (effectively an event pulisher)
  public IObservable<EventPattern<MyEventArgs>> MyEventPublisher
  {
    get
    {       // To consume SimpleEvent as an IObservable:
        IObservable<EventPattern<MyEventArgs>> eventAsObservable = Observable.
            FromEventPattern<MyEventArgs>(
              ev => SimpleEvent += ev,
              ev => SimpleEvent -= ev);
        return eventAsObservable;
    }
  }

}

Note that MyEventArgs is something derived from EventArgs that allows access to the "MyEvent" instance, see below. Here is a tester:

public void TestSimpleEventSource()
{
    var ses = new SimpleEventSource();
    ses.FireSimpleEvent(new MyEvent("1st event")); // This one is missed

    using (var subscription = ses.MyEventPublisher.Subscribe(
        ev => Console.WriteLine(ev.EventArgs.MyEvent.Text + " fired")))
    {
        ses.FireSimpleEvent(new MyEvent("2nd event"));
        ses.FireSimpleEvent(new MyEvent("3rd event"));               
    }

    Console.WriteLine("Subscription cancelled");
}
and the output
2nd event fired
3rd event fired
Subscription cancelled

Replacing C# Events using Reactive Extensions

Lets take this one step further, and completely replace the C# event with a reactive style event publisher

internal class SimpleEventSource
{
    private Subject<MyEvent> _myEventSubject = new Subject<MyEvent>();

    public IObservable<MyEvent> MyEventPublisher => this._myEventSubject.AsObservable();

    public void FireSimpleEvent(MyEvent myEvent) => this._myEventSubject.OnNext(myEvent);
}
And the same test but using this class:
public void TestSimpleEventSource2()
{
    var ses = new SimpleEventSource2();
    ses.FireSimpleEvent(new MyEvent("1st event"));

    using (var subscription = ses.MyEventPublisher.Subscribe(
        ev => Console.WriteLine(ev.Text + " fired")))
    {
        ses.FireSimpleEvent(new MyEvent("2nd event"));
        ses.FireSimpleEvent(new MyEvent("3rd event"));
    }

    Console.WriteLine("Subscription cancelled");
}

Here is the code for the simple event classes if it makes things clearer

public class MyEvent
{
    public MyEvent(string text)
    {
        Text = text;
    }
    public string Text { get; private set; }
}

public class MyEventArgs : EventArgs
{
    public MyEventArgs(MyEvent myEvent)
        : base()
    {
        MyEvent = myEvent;
    }
    public MyEvent MyEvent { get; private set; }
}

August 20, 2021

Stopwatch Extension

Some simple code to use a Stopwatch class to measure how long a piece of code takes to run. With this extension you can forget about the Stopwatch syntax:

namespace Utilities.StopwatchExtensions
{
  public static class StopwatchExtender
  {
    public static TimeSpan MeasureRunTime(this Action codeToRun)
    {
        var stopWatch = Stopwatch.StartNew();
        codeToRun();
        stopWatch.Stop();
        return stopWatch.Elapsed;
    }
  }
}

From .NET 7.0 you can use this form:

namespace Utilities.StopwatchExtensions
{
  public static class StopwatchExtender
  {
    public static TimeSpan MeasureRunTime(this Action codeToRun)
    {
        long startTime = Stopwatch.GetTimestamp();;
        codeToRun();
        TimeSpan elapsedTime = Stopwatch.GetElapsedTime(startTime);
    }
  }
}
Remember to wrap the extension in a specific isolating namespace otherwise the intelli-editor in Visual Studio will get polluted with unused extension methods. To use:
Action codeToRun = () => { /* code whose execution time needs measuring */};
var runTimeMs = codeToRun.MeasureRunTime().TotalMilliseconds;
Trace.WriteLine("*** Time to complete task: " + runTimeMs + " ms");

using (var process = Process.GetCurrentProcess())
{
    Trace.WriteLine($"*** Execution time: {runTimeMs.ToString()} ms");
    Trace.WriteLine($"*** Gen-0: {GC.CollectionCount(0).ToString()}");
    Trace.WriteLine($"*** Gen-1: {GC.CollectionCount(1).ToString()}");
    Trace.WriteLine($"*** Gen-2: {GC.CollectionCount(2).ToString()}");
    Trace.WriteLine($"*** Peak WrkSet: {process.PeakWorkingSet64.ToString("n0")}");
}

August 19, 2021

C# Event Aggregators

Did some research into event aggregators. They are a great way to allow events to be fired betwen classes without the classes being tightly coupled, in other words without either class having to know about the other. Standard C# events make the classes tighly coupled, the listener needs to know about the firer. Sometimes with standard c# events, an event will need to be transmitted through an intermediate sequence of objects just to reach the target recipient, this is very cumbersome and laborious. Event aggregators completely decouple the event publishers from the event subscribers as long as both subscriber and publisher objects can access the event aggregator their is no need for intermediate objects to relay the events

Would make an excellent start for a simulator which has both hardware and software events occuring, an event aggregator could be used to input events to the system. As it is completely decoupled from the system, it would be easy to emulate firing these software events say from a GUI for emulation purposes, and also easy to connect to real hardware to populate those same software events.

I found several links that use a Reactive Extensions to implement an Event Aggregator. Using the Reactive Extensions the code to implement an aggregator is very small and compact.

  1. https://mikebridge.github.io/post/csharp-domain-event-aggregator
It is also a great example in the usage of Reactive Extensions. Currently I have combined them into this form:

using System.Reactive.Linq; // You'll need the Reactive nuget package
using System.Reactive.Subjects;
...

public interface IRxEventAggregator : IEventAggregator, IDisposable
{
    /// <summary>
    ///  Use this method to apply RX (LINQ style) expressions on
    ///  the events before subscribing
    /// </summary>
    /// <typeparam name="TEvent"></typeparam>
    /// <returns></returns>
    IObservable<TEvent> GetEventsObservable<TEvent>();
}

public interface IEventAggregator
{
    IDisposable Subscribe<T>(Action<T> action);
    void Publish<T>(T @event);
}


/// <summary>
/// An EventAggregator that is based on reactive extensions and supports
/// </summary>
public class RxEventAggregator
    : IRxEventAggregator
{
    readonly Subject<object> _subject = new Subject<object>();

    // Use this method to use RX (LINQ style) expressions
    // on the events before subscribing
    public IObservable<TEvent> GetEventsObservable<TEvent>()
    {
        return _subject.OfType<TEvent>().
            AsObservable();
    }

    public IDisposable Subscribe<T>(Action<T> action)
    {
        return GetEventsObservable<T>().
            Subscribe(action);
    }

    public void Publish<TEvent>(TEvent sampleEvent)
    {
        _subject.OnNext(sampleEvent);
    }

    #region IDisposable

... // See below

    #endregion
}

Generally an Event Aggregator lives throughout the life of your software so it really does not need disposing of. You could remove the Dispose code completely. For that reason I list it here just for reference:

    #region IDisposable

    bool _disposed;

    ~RxEventAggregator()
    {
        Dispose(false);
         // Useful for detecting memory leaks
        Debug.Assert(false, nameof(RxEventAggregator) + 
            " was not disposed of");
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); 
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed) return;

        _subject.Dispose();
        _disposed = true;
    }

    #endregion

Here's another event aggregator:

// When there are a lot of events with lots of subscribers
public class RxEventAggregator
: IRxEventAggregator
{
    private volatile ConcurrentDictionary<Type, object> _subjects
        = new ConcurrentDictionary<Type, object>();

    // Use this method to use RX (LINQ style) expressions
    // on the events before subscribing
    public IObservable<TEvent> GetEventsObservable<TEvent>()
    {
        Trace.Assert(!_disposed, "Trying to access a disposed EventAggregator");
        var subject =
            (ISubject<TEvent>)_subjects.GetOrAdd(typeof(TEvent),
                        _ => new Subject<TEvent>());
        return subject.AsObservable();
    }

    public IDisposable Subscribe<T>(Action<T> action)
    {
        Trace.Assert(!_disposed, "Trying to access a disposed EventAggregator");
        return GetEventsObservable<T>().
            Subscribe(action);
    }

    public void Publish<TEvent>(TEvent sampleEvent)
    {
        Trace.Assert(!_disposed, "Trying to access a disposed EventAggregator");
        if (_subjects.TryGetValue(typeof(TEvent), out var subject))
        {
            ((ISubject<TEvent>)subject)
                .OnNext(sampleEvent);
        }
    }

    // If your Aggregator is a life (of the application) long one you can simply not bother with disposing of it
    #region IDisposable 

    bool _disposed;

    ~RxEventAggregator2()
    {
        Debug.Assert(false, nameof(RxEventAggregator2) + " was not disposed of"); // Useful for detecting memory leaks
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);  // no need to call finalizer now
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed) return;

        _disposed = true;
        // Make them unaccessible
        var hiddenSubjects = Interlocked.Exchange(ref _subjects, new ConcurrentDictionary<Type, object>());
        // Then dispose of them
        foreach (var subject in hiddenSubjects.Values.Cast<IDisposable>())
        {
            subject.Dispose();
        }

    }

    #endregion
}

August 12, 2021

New Project File Format (VS 2017/2019)

There is a new alternative project file format from Visual Stuidio 2017 onwards. Checkout this description here

Here is an example of a WPF project file
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

Note the "TargetFramework" of ".net5.0-windows" is required for WinForms, WPF applications. These are supported in .NET 5.0 but only as windows applications.

Here is a library project that will build to multiple .Net versions both core and frameworks

<Project Sdk="Microsoft.NET.Sdk">
  <!-- Main build info -->
  <PropertyGroup>
    <TargetFrameworks>net48;net5.0</TargetFrameworks>
    <PackageId>MyProject</PackageId>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <SignAssembly>false</SignAssembly>
  </PropertyGroup>
  
  <!-- Assembly Info -->
  <PropertyGroup>
    <AssemblyVersion>3.7.2.3</AssemblyVersion>
    <Description>An implementation of MyProject.</Description>
    <Authors>Joe Blogz</Authors>
    <Copyright>2019 Magicsoft Corp.</Copyright>
    <Company>Magicsoft Corp.</Company>
    <PackageTags>Subject1;Subject2</PackageTags>
    <PackageProjectUrl>https://myproject.com/url</PackageProjectUrl>
    <PackageLicenseExpression>MIT</PackageLicenseExpression>
    <PackageReleaseNotes>-</PackageReleaseNotes>
  </PropertyGroup>
  
  <!-- Repo Info -->
  <PropertyGroup>
    <RepositoryUrl>https://github.com/MyProject</RepositoryUrl>
    <RepositoryType>git</RepositoryType>
  </PropertyGroup>

  <!-- Remove AssemblyInfo.cs from build (in Properties dir.) -->
  <!-- it is now in the project file -->
  <ItemGroup>
    <Compile Remove="Properties\**" />
    <EmbeddedResource Remove="Properties\**" />
    <None Remove="Properties\**" />
  </ItemGroup>

  <!-- NUnit packages go here -->
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
    <PackageReference Include="System.ValueTuple" Version="4.5.0" />
  </ItemGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'net5.0' ">
    <Compile Remove="MyProject (net48)\**" />
  </ItemGroup>
</Project>

For multiple frame work targets <TargetFramework>..<TargetFramework> is replaced with <TargetFrameworks>...<TargetFrameworks> Note that .Net farmeworks use the style netnn where nn is the version but .Net version 5.0 onwards (which are .NET Core frameworks) use the form netn.n where n.n represesnt the .NET version. See https://docs.microsoft.com/en-us/dotnet/standard/frameworks for all possible entries

Note that the version info can be removed from the Assembly.cs and placed into the project file now. Referencing Nuget packages is also simplified.

Projects can be migrated with the help of the CsprojToVs2017 tool. Don't bother downloading the source and building it yourself, instead install it quickly using the dotnet install tool. This is described in the Quick Start Section. It will do most of the work of porting projects accross from the old format for you.

Some parts of a project file can be conditional, this feature is described here. For example in the project above I had to exclude some files that would only build in .NET Framework 4.8 or less. I placed these files in a subdirectory "CommonCore (net48)" and exclude them from the .NET 5.0 build.

Task.IsCompletedSuccessfully Property Extension

Task in all versions of the the .Net framework and .Net Standard 2.0 has a useful property missing. From .Net Standard 2.1 and through all versions of .Net Core the "IsCompletedSuccessfully" property is available. This will tell the use that the task completed without throwing an exeception or because it was cancelled. Well we can use an extension to make up for this missing property.

namespace System.Threading.Tasks
{
  public static class TaskIsCompletedSuccessfullyExtension
  {
    public static bool IsCompletedSuccessfully(this Task task)
    {
      var value = task.IsCompleted && !(task.IsCanceled || task.IsFaulted);
      return value;
    }
  }
}
and to use:
using System.Threading.Tasks;
...

Task myTask = ...

// Note it is defined not as a property but as a method
if (myTask.IsCompletedSuccessfully())
{
...
}

Using CallMemberAttribute in an INotifyPropertyChanged Base Class

Here is an sample base clase that makes implementing INotifyPropertyChanged easy. It is also a nice example of using templated methods on a class in C# without making the whole class templated.
using System.Runtime.CompilerServices;
...

public abstract class NotifyProperyChangedBase : INotifyPropertyChanged
{
    /// <summary>
    /// Multicast event for property change notifications.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    ///     Checks if a property already matches a desired value.
    ///     Sets the property and
    ///     notifies listeners only when necessary.
    /// </summary>
    /// <typeparam name="T">Type of the property.</typeparam>
    /// <param name="storage">Reference to a property with 
    /// both getter and setter.</param>
    /// <param name="value">Desired value for the property.</param>
    /// <param name="propertyName">
    ///     Name of the property used to notify listeners.  This
    ///     value is optional and can be provided automatically 
    ///     when invoked from compilers that support CallerMemberName.
    /// </param>
    /// <returns>
    ///     True if the value was changed, false if the existing
    ///     value matched the desired value.
    /// </returns>
    protected bool SetProperty<T>(
        ref T storage, 
        T value, 
        [CallerMemberName] String propertyName = null)
    {
        bool valueChanged = !EqualityComparer<T>.Default.Equals(storage, value);
        if (valueChanged)
        {
            storage = value;
            OnPropertyChanged(propertyName);
            valueChanged = true;
        }
        return valueChanged;
    }

    /// <summary>
    ///     Checks if a property already matches a desired value.
    ///     Sets the property and notifies listeners only when 
    ///     necessary.
    /// </summary>
    /// <typeparam name="T">Type of the property.</typeparam>
    /// <param name="storage">Reference to a property 
    /// with both getter and setter.</param>
    /// <param name="value">Desired value for the property.</param>
    /// <param name="equalityComparer">
    ///     Specify the equality comparer.
    ///     For example if it is a non-case sensitive string you could use
    ///     StringComparer.CurrentCultureIgnoreCase</param>
    /// <param name="propertyName">
    ///     Name of the property used to notify listeners.  This
    ///     value is optional and can be provided automatically
    ///     when invoked from compilers that support CallerMemberName.
    /// </param>
    /// <returns>
    ///     True if the value was changed, false if the existing
    ///     value matched the desired value.
    /// </returns>
    protected bool SetProperty<T>(
        ref T storage, 
        T value, 
        IEqualityComparer<T> equalityComparer,
        [CallerMemberName] String propertyName = null)
    {
        bool valueChanged = !equalityComparer.Equals(storage, value);

        if (valueChanged)
        {
            storage = value;
            OnPropertyChanged(propertyName);
            valueChanged = true;
        }

        return valueChanged;
    }

    /// <summary>
    ///     Notifies listeners that a property value has changed.
    /// </summary>
    /// <param name="propertyName">
    ///     Name of the property used to notify listeners. This
    ///     value is optional and can be provided automatically
    ///     when invoked from compilers that support 
    ///     <see cref="CallerMemberNameAttribute" />.
    /// </param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
and here is an example usage inside a ViewModel class:
private string _notifyIconToolTipText = "";

public string NotifyIconToolTipText
{
    get
    {
        return _notifyIconToolTipText;               
    }
    set
    {
        string newValue = value ?? "";
        this.SetProperty(ref _notifyIconToolTipText, newValue);
    }
}