Building refactoring-friendly observable objects in C#


INotifyPropertyChanged is one the most frequently used .NET interfaces nowadays. I use this interface every day within the models in all kinds of applications: Windows Forms, WPF, Silverlight.

However there is one disadvantage in using INotifyPropertyChanged I have to deal with very often – it is not “refactoring-friendly” and requires a lot of efforts when supporting large scalable enterprise applications/frameworks.

Here’s a skeleton of a common observable object exposing INotifyPropertyChanged interface we all usually deal with:

public class MyCommonObject : INotifyPropertyChanged
{
  #region INotifyPropertyChanged Members

  public event PropertyChangedEventHandler PropertyChanged;

  protected void OnPropertyChanged(string propertyName)
  {
    var handler = PropertyChanged;
    if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName));
  }

  #endregion
}

 

Now let’s take a “Name” property that supports value change notifications:

public class MyCommonObject : INotifyPropertyChanged
{
  private string _Name;

  public string Name
  {
    get { return _Name; }
    set
    {
      if (_Name == value) return;
      _Name = value;
      OnPropertyChanged("Name");
    }
  }

  #region INotifyPropertyChanged Members  
  #endregion
}

 

When you want to rename “Name” property above to something like “FirstName” using some refactoring tool the notification will work properly only when the “OnPropertyChanged” call argument is changed as well. It is quite easy to change the code above to call OnPropertyChanged(“FirstName”) but it’s not so easy when you deal with hundreds of objects with possibly hundreds of properties spread over more than one project/solution. Sometimes it is not only the property who notifies about value changes and this makes the refactoring/support task extremely difficult and error-prone.

Being tired of searching broken “OnPropertyChanged” occurrences I’ve started to think over modifying this pattern in order to make it “refactoring-aware”. I wanted to pass something like a “pointer” to the property rather than it’s name so that each time the property name is changed the “pointer” does not require additional tuning. After trying out several approaches I finally found the one that perfectly suits my needs.

Linq Expressions to the rescue…

I’ve decided to reuse Linq Expressions and lambda Functions in order to pass a strongly-typed reference to the object’s property for the “OnPropertyChanged” method. I ended with the following modification of basic “INotifyPropertyChanged” implementation:

public class ObservableObject<T> : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged(Expression<Func<T, object>> property)
  {
    if (property == null || property.Body == null) return;

    var memberExp = property.Body as MemberExpression;
    if (memberExp == null) return;
    
    var handler = PropertyChanged;
    if (handler != null)
      handler(this, new PropertyChangedEventArgs(memberExp.Member.Name));
  }

As you can see “OnPropertyChanged” method was changed to receive Expression<Func<T, object>> instead of a string-based property name.

You don’t need compiling or executing this expression. The primary goal is accessing its Body that is represented by a MemberExpression. MemberExpression instance wraps a common “System.Reflection.MemberInfo” as a Member property and so it is obvious that you can get the actual name of the property based on reflection and create a proper event arguments on the fly.

Note: This is a basic implementation and does not consider various possible scenarios. I simply exit method execution if things go the unexpected way. You may want providing some exceptions or error handling.

As you may have noticed I’ve provided a generic class implementation that can be consumed by my objects. Here’s a basic sample of the object consuming modified pattern:

public class MyObject : ObservableObject<MyObject>
{
  private bool _BoolProperty;
  public bool BoolProperty
  {
    get { return _BoolProperty; }
    set
    {
      if (_BoolProperty == value) return;
      _BoolProperty = value;
      OnPropertyChanged(@this => @this.BoolProperty);
    }
  }

  private int _IntProperty;
  public int IntProperty
  {
    get { return _IntProperty; }
    set
    {
      if (_IntProperty == value) return;
      _IntProperty = value;
      OnPropertyChanged(@this => @this.IntProperty);
    }
  }

  private string _StringProperty;
  public string StringProperty
  {
    get { return _StringProperty; }
    set
    {
      if (_StringProperty == value) return;
      _StringProperty = value;
      OnPropertyChanged(@this => @this.StringProperty);
    }
  }

  private object _ObjectProperty;
  public object ObjectProperty
  {
    get { return _ObjectProperty; }
    set
    {
      if (_ObjectProperty == value) return;
      _ObjectProperty = value;
      OnPropertyChanged(@this => @this.ObjectProperty);
    }
  }
}

 

I guess the sample above does not need detailed comments. Instead of string-based property name you now pass the property. If you or someone else decides refactoring the name of the property all notification logic will be automatically updated.

Proper implementation

However when running the following test I found that the code above was not working as expected:

class Program
{
  static void Main(string[] args)
  {
    MyObject my = new MyObject();
    my.PropertyChanged += (sender, e) => Console.WriteLine(e.PropertyName);

    my.BoolProperty = true;
    my.IntProperty = 100;
    my.StringProperty = "something";
    my.ObjectProperty = 100;

    Console.WriteLine("Press Enter to exit...");
    Console.ReadLine();
  }
}

I was receiving only notifications for “StringProperty” and “ObjectProperty” properties, but nothing for “BoolProperty” and “IntProperty”.

After some investigation I found out that my problem was in “object” declaration in Expression<Func<T,object>>. Linq wraps value type instances with additional “Convert” expression so my check for “MemberExpression” was receiving null value during type casting.

This produced another slight modification that covered all aspects of expression passing:

public class ObservableObject<T> : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged(Expression<Func<T, object>> property)
  {
    if (property == null || property.Body == null) return;

    var memberExp = property.Body as MemberExpression;
    if (memberExp == null)
    {
      UnaryExpression unary = property.Body as UnaryExpression;
      if (unary != null) memberExp = unary.Operand as MemberExpression;
      if (memberExp == null) return;
    }

    var handler = PropertyChanged;
    if (handler != null)
      handler(this, new PropertyChangedEventArgs(memberExp.Member.Name));
  }
}

As you can see I’ve added a fallback step to check whether an Unary Expression is actually being received. In this case I’m taking it’s Operand as the expected Member expression and this works like magic. Now my test output is correct and provides notification for all the properties.

Notes

The approach above consumes more CPU cycles than the common INotifyPropertyChanged use so it might slightly decrease performance. However I’m sure it may greatly reduce the cost of code support in future and save your time and money.

Feel free playing with the source code for this article.

Advertisements

Windows Automation: Automating Windows 7 Notepad within S# Script


Today we have updated S# with another sample covering the use of Windows Automation API from within a common S# script.

Auto# (AutoSharp)

This is a demo project shows how easily your S# scripts can be enhanced with a set of functions that target Windows UI Automation API and the ways of forming a QA-friendly language on the top of S# runtime. Full source code for this sample is available within the latest S# runtime update here.

Note: Sample project targets Windows 7 Notepad and may not work properly on other versions of Windows because of control ids difference.

To find Windows Automation API for your version of Windows please refer to this article.

Auto# introduces 9 functions that provide Windows Automation support S# scripts:

  • Kill – close all running instances of some process
  • Launch – launch a new process and return its main window
  • Wait – sleep for some time, often required when waiting application response
  • FindByClassName – finds element by Class Name
  • FindById – finds element by Automation ID
  • FindByName – finds element by its Name
  • Expand – expands menu element
  • InvokeById – invokes element by Automation ID
  • FocusEditor – focuses textbox editor

The following workflow is executed in order to automate Notepad:

  1. Kill all running Notepad instances
  2. Launch a new Notepad process
  3. Type some text
  4. Click “File” – “Save As” in the main menu
  5. Type destination file name
  6. Agree to overwrite existing file if confirmation dialog appears
  7. Click “File” – “Exit” to close Notepad

Here’s how the S# script may look like:

// Close existing instances of Notepad

Kill(“notepad”);

 

// Launch a new Notepad instance and get main window

window = Launch(“notepad”);

// Wait 1 second

Wait(1000);

 

// Get main editor region

edit = FindByClassName(window, “Edit”);

 

// focus main editor

FocusEditor(edit);

 

// Send sample text to the editor region

SendKeys.SendWait(“Automating Notepad using Windows UI Automation and S#”);

Wait(3000);

 

// Find [File] menu

mnuFile = FindById(window, “Item 1”);

 

// Expand [File] menu

Expand(mnuFile);

Wait(1000);

 

// Invoke [Save As] menu item

InvokeById(window, “Item 4”);

Wait(1000);

 

// Get [Save As] dialog

saveAsDialog = FindByName(window, “Save As”);

 

// Get access to [FileName] textbox

saveAsName = FindById(saveAsDialog, “1001”);

 

// Focus filename editor

FocusEditor(saveAsName);

 

// Write down file name

SendKeys.SendWait(“D:\\MyTextFile”);

// Send [Enter] keypress

SendKeys.SendWait(“{ENTER}”);

Wait(1000);

 

// Check whether Overwrite Dialog appeared

confirmSaveAs = FindByName(saveAsDialog, “Confirm Save As”);

if (confirmSaveAs != null)

{

    // Click [OK] button

    InvokeById(confirmSaveAs, “CommandButton_6”);

    Wait(1000);

}

 

// Expand [File] menu

Expand(mnuFile);

Wait(1000);

 

// Click [Exit] item

InvokeById(window, “Item 7”);

 

 

Demo project also includes a very simply UI providing possibility to alter the script above and execute it.

Unleash your fantasy 🙂

S# 1.1 and Processing# Visualization Language for Silverlight 3.0


We are happy to announce that S# 1.1 was released today.

“Extension Methods”

It is now possible extending .NET types with custom methods that can be invoked during script execution. It is not the support for.NET extension methods but functionality is somewhat similar.

Let’s take a .NET “System.Math” class. It is a static class that “Provides constants and static methods for trigonometric, logarithmic, and other common mathematical functions”. You can freely access all its members from S# script (omitting namespace) but at some point you may want to extend existing set of methods with some custom or missing (in your opinion) ones. For example conversion to radians, mapping/constraint of numeric values, distance calculation, etc. But “System.Math” is a static class and cannot be inherited for customization purpose.

In S# 1.0 we used the following workaround for such cases: we would have created a “MathEx” class to mimic “System.Math” one with same methods being re-directed to original “Math” plus containing additional members like “Distance()”, “Radians()” etc. After that we’ve been suppressing original “Math” class with our own implementation with the help of RuntimeHost features like “AddType”: RuntimeHost.AddType(“Math”, typeof(MathEx)); From that moment all “Math.*” calls were redirected to a custom implementation and original “System.Math” was hidden from the scripts.

Though the approach above is still valid and you can easily suppress any type with your own implementation we decided to provide an out-of-box support in S# 1.1 for such scenarios:


RuntimeHost.TypeManager

.AddExtensionMethod(typeof(Math), “Constrain”, new
MathExtensions.Constrain())

.AddExtensionMethod(typeof(Math), “Degrees”, new
MathExtensions.Degrees())

.AddExtensionMethod(typeof(Math), “Distance”, new
MathExtensions.Distance())

.AddExtensionMethod(typeof(Math), “Distance2D”, new
MathExtensions.Distance2D())

.AddExtensionMethod(typeof(Math), “Distance3D”, new
MathExtensions.Distance3D())

.AddExtensionMethod(typeof(Math), “Map”, new
MathExtensions.Map())

.AddExtensionMethod(typeof(Math), “Radians”, new
MathExtensions.Radians());

Now you can create invokable functions and bind them to ANY .net type with a single line of code. The sample above demonstrates how easily “System.Math” type is enriched with 7 new methods. Here’s how I’m using it now within my scripts:

ang1 = Math.Radians(i); // convert degrees to radians

ang2 = Math.Radians(j); // convert degrees to radians

pos1 = Surface.Width/2 + (sc * Math.Cos(ang1));

pos2 = Surface.Width/2 + (sc * Math.Sin(ang1));

pos3 = Surface.Width/2 + (sc * Math.Cos(ang2));

pos4 = Surface.Width/2 + (sc * Math.Sin(ang2));

We hope this feature will greatly reduce development efforts for numerous scenarios as well as well as enrich your scripts.

Processing# Visualization Language for Silverlight 3.0

“Processing#” is a showcase sample demonstrating most of the powerful capabilities of S#. Being greatly inspired by “Processing” language implementation in Java we decided to port it to Silverlight powering with S# runtime. After installing S# 1.1 runtime you will find the complete source code under the “Samples\Silverlight 3.0” folder.

Solution contains a simple console where you can write and immediately execute scripts. There are more than 30 “Processing.org” samples that were successfully ported to “Processing#” and that are available within the Silverlight console. The syntax was made slightly different by intention and will be getting more parity in later versions.

Source code also contains a ported to Silverlight demo from “OpenProcessing.org” to demonstrate the capabilities of Processing# powered by S# 1.1 runtime:

function Setup()

{

 

Surface.Size(320, 480);

 

//Main Body

Surface.Defaults.StrokeThickness = 2;

Surface.Defaults.Fill = new SolidColorBrush(Color.FromArgb(255, 203, 224, 142));

 

using (Surface)

{

    BeginShape();

    Vertex(154, 65);

    Vertex(182, 71);

    Vertex(225, 82);

    Vertex(250, 90);

    Vertex(258, 96);


The image above is rendered by Silverlight 3 and has no visual difference comparing to that created by Java.

You can download the latest runtime with Processing# demo here: Orbifold S# Runtime 1.1