ILoggable

A place to keep my thoughts on programming

 Subscribe

geekblog
[at]
claassen [dot] net

Powered by Blogger

Sunday, September 23, 2007

Automatic properties syntax wish

Just a quick thought on on Automatic properties in C# 3.0 (.NET 3.5, Orcas, whathaveyou). I, like most .NET developers, have spent too much time writing
private string foo;

public string Foo
{
 get { return foo; }
 set { foo = value; }
}
This can now be replaced with
public string Foo { get; set; }
Now that's nice and all, but for the most part it doesn't seem like a big step up from just making your field public. Now, you do get the benefit of being able to use this property in places where reflection is used for exposing properties, i.e. in most data-binding scenarios, which don't accept public fields. And it let's you implement interfaces, since they also can't define public fields. But that's a lot more useful, at least to me is replacing
private string foo;

public string Foo { get { return foo; } }
with
public string Foo { get; private set; }
Now you can create those read-only properties with very simple, clean syntax. That'll clean up a lot of code for me. But finally we still have the scenario where properties have side-effects, like calling the event trigger for INotifyPropertyChanged. This cannot be expressed with automatic properties and we're back to defining a separate private field. What I would love to see is some syntactic sugar along the lines of
public string Foo
 : private _foo
{
 get;
 set
 {
   string previous = _foo;
   _foo = value;
   if(previous != _foo)
   {
     OnPropertyChanged("Foo");
   }
 }
}
I know this doesn't buy that much in syntax terseness (the get is shorter and you don't have to define the type of _foo), but it means that the private storage used by the property is part of the property definition, which makes the definition that much more easy to read, imho. That, or allow pre and post conditions for set in Automatic Properties, although the syntax i can think of for that doesn't seem cleaner than the above.

Labels: , ,

Tuesday, July 10, 2007

A generic asynchronous INotifyPropertyChanged helper

The other day I was lamenting what I consider to be an omission in Data-binding's responsibilities, i.e. the lack of invocation of an INotifyPropertyChanged PropertyChanged event on the appropriate UI thread. Instead, INotifyPropertyChanged implementors are expected to be updated only on the UI thread in order to work.

I figured I should be able to throw a proxy between the actual INotifyPropertyChanged implementor and the binding, and have this proxy be instantiated with awareness of the observing form. Thus the proxy could do the invocation on the UI thread and still let me use INotifyPropertyChanged without creating a dependency on knowing that the object was being observed by a UI element. That line of thought lead to worked as a static proxy, that I had to create by hand. Once I switched to Castle's Dynamic Proxy, it didn't work anymore, the event somehow being swallowed along the way.

I also considered looking at creating my own BindingContext but that didn't bear fruit either. It was then that I realized that I didn't need to create a proxy that matched my source object, since data binding didn't care what it bound to, as long as it had the dataMember it was being told about. I started down a path of creating a wrapper class using Reflection.Emit when I further reasoned that even the dataMember that's exposed doesn't have to match the one of the data source. This opened the door to just using dynamic property invocation and a simple generic helper class emerged:

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;

namespace FullMotion.Helpers
{
  /// <summary>
  /// A helper class for creating a binding on an object that may be changed
  /// asynchronously from the bound UI thread.
  /// </summary>
  public class AsyncBindingHelper : INotifyPropertyChanged
  {
    /// <summary>
    /// Get a binding instance that can invoke a property change
    /// on the UI thread, regardless of the originating thread
    /// </summary>
    /// <param name="bindingControl">The UI control this binding is added to</param>
    /// <param name="propertyName">The property on the UI control to bind to</param>
    /// <param name="bindingSource">The source INotifyPropertyChanged to be
    /// observed for changes</param>
    /// <param name="dataMember">The property on the source to watch</param>
    /// <returns></returns>
    public static Binding GetBinding( Control bindingControl,
                                      string propertyName,
                                      INotifyPropertyChanged bindingSource,
                                      string dataMember )
    {
      AsyncBindingHelper helper 
        = new AsyncBindingHelper(bindingControl,bindingSource,dataMember);
      return new Binding(propertyName,helper,"Value");
    }

    Control bindingControl;
    INotifyPropertyChanged bindingSource;
    string dataMember;

    private AsyncBindingHelper( Control bindingControl,
                                INotifyPropertyChanged bindingSource, 
                                string dataMember )
    {
      this.bindingControl = bindingControl;
      this.bindingSource = bindingSource;
      this.dataMember = dataMember;
      bindingSource.PropertyChanged 
        += new PropertyChangedEventHandler(bindingSource_PropertyChanged);
    }

    void bindingSource_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      if (PropertyChanged != null && e.PropertyName == dataMember)
      {
        if (bindingControl.InvokeRequired)
        {
          bindingControl.BeginInvoke(
            new PropertyChangedEventHandler(bindingSource_PropertyChanged),
            sender,
            e );
          return;
        }
        PropertyChanged(this, new PropertyChangedEventArgs("Value"));
      }
    }

    /// <summary>
    /// The current value of the data sources' datamember
    /// </summary>
    public object Value
    {
      get
      {
        return bindingSource.GetType().GetProperty(dataMember)
          .GetValue(bindingSource,null);
      }
    }
    #region INotifyPropertyChanged Members
    /// <summary>
    /// Event fired when the dataMember property on the data source is changed
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
  }
}

To use this class, simply replace this:

myLabel.DataBindings.Add("Text", myDataSource,"MyProperty");
with this:
myLabel.DataBindings.Add(
  AsyncBindingHelper.GetBinding(myLabel, "Text", myDataSource,"MyProperty") );

The one tricky thing about this is that it may cause uncollectable references. We're creating an instance of AsyncBindingHelper behind the scenes that sets up an event handler on our binding source. Which means we can't get rid of that event subscription. Theoretically, once the binding control goes out of scope, the helper should also go out of scope, relinquishing the reference it holds on the binding source.

The other thing that would be simple to do is to turn this helper into an Extension Method on INotifyPropertyChanged, once I move my code over to Orcas. That way creating an asynchronous binding on an instance of INotifyPropertyChanged would become even cleaner and straight forward.

Labels: , , , ,

Sunday, July 08, 2007

INotifyPropertyChanged and Cross-thread exceptions

I'm currently reading Adam Nathan's WPF Unleashed. It's a good read and has me ready for doing some serious WPF work. However, the things I have on my plate are a already Windows Forms and can't really take a late in the project UI architecture change, so my production use of WPF will have to wait a little longer. I originally thought WPF was horribly over-engineered, but going through Adam's book, the decisions that led to the sometimes odd APIs make sense. It's clear that toolability of Xaml, separation of logic and code and allowing the greatest amount of design without any code are what led to the cumbersome manual C# syntax. But once you mix in Expression Blend, you won't be doing any of those nasty things unless you're writing your own custom controls. Ok, this is a lovely tangent, but hardly the subject of this entry...

While reading I came across INotifyPropertyChanged. Since it's meant for binding in general, I thought this might be a perfect fit for a design issue I was having on a WinForms project. Basically, I have an object that manages a native process and can get manipulated via remoting. The UI in the program really just exists for status updates on this management object. The solution for keeping the UI in sync was either a timer that polled the object's properties or create an event for each property change, manually subscribe to them in the form and update the UI that way. However, INotifyPropertyChanged provided a simple methodology for tracking changes in all objects and let the implementing object be used for data-binding. I'm usually against code that uses strings to reference object members, like data-binding is wont to do, since it falls outside of compile-time checking and is liable to get out of sync in refactoring, but data-binding is convenient and so prevalent in .NET, that I decided to use it for this.

Implementing INotifyPropertyChanged on my object was dead simple and the syntax for binding my labels to property changes was even easier. Perfect, another process simplified. Or so I thought. What happened next is what I personally would describe as a bug or at least mis-feature in data binding, but at least according to the docs, it's by design.

INotifyPropertyChangeddoes not work for asynchronous operations

What happened was this: I made changes to my object via the remoting proxy and my client UI died with an InvalidOperationException(Cross-thread operation not valid...). On it's face this is straight forward: My object is on a background thread, being manipulated by remoting. My UI is on the UI thread, so tweaking the UI by the background thread is a no-no. This is confirmed by the MSDN documentation which says:

If your data source implements the INotifyPropertyChanged and you are performing asynchronous operations you should not make changes to the data source on a background thread. Instead, you should read the data on a background thread and merge the data into a list on the UI thread.

That to me is bad advice and a lazy way of saying that data binding doesn't do its due diligence on binding operations. Why? Well, the purpose of something like INotifyPropertyChanged is Separation of Concerns, decoupling the observer of the property data from the observable object. But what the above says is that the observed object is responsible for knowing how it might be observed.

The logical thing is that your INotifyPropertyChanged object neither knows nor should care that it's data may be used to update the UI on another thread. The party that's responsible for that bit of house-keeping is the one that does the actual updating of the UI controls, i.e. data-binding. Data-binding is intimately aware of the UI object it's tied to and it's the one that isactually updating the UI in response to an incoming event. It seems logical and practical that it would do the necessary check on Control.InvokeRequired and perform said invoke. Instead telling you that your object better live on the UI thread is just not very good advice, imho.

Where does that leave us?

Well, even if the business object wanted to invoke on the UI thread, it couldn't unless it was aware of the UI thread, and that once again violates the Separation of Concerns that should exist between business logic and UI. So that leaves us with two options: a) change the way binding works to the way described above or b) put a proxy between the binding and the INotifyPropertyChanged implementor.

Since you can assign a new BindingContext to a control, a) may be an option, and it's one I'm going to investigate next. However for the time being, going down the path of b) was simpler.

I hardcoded a proxy for my business object, had it implement INotifyPropertyChanged as well and created a factory that would take both the form and the proxied object to create a new proxy. The proxy then subscribed to the proxied PropertyChanged event and used its reference to the form to make sure it was invoked on the UI thread.

public class MyBusinessObject : INotifyPropertyChanged
{
  [...]
  public int MyProperty
  {
    get { [...] }
  }
  [...]
}

public class MyBusinessObjectProxy : INotifyPropertyChanged
{
  Control bindingControl;
  MyBusinessObject bindingSource;

  private MyBusinessObjectProxy(Control bindingControl, MyBusinessObject bindingSource)
  {
    this.bindingControl = bindingControl;
    this.bindingSource = bindingSource;
    bindingSource.PropertyChanged += new PropertyChangedEventHandler(bindingSource_PropertyChanged);
  }

  void bindingSource_PropertyChanged(object sender, PropertyChangedEventArgs e)
  {
    if (PropertyChanged != null)
    {
      if (bindingControl.InvokeRequired)
      {
        bindingControl.BeginInvoke(new PropertyChangedEventHandler(bindingSource_PropertyChanged), sender, e);
        return;
      }
      PropertyChanged(this, new PropertyChangedEventArgs(e.PropertyName));
    }
  }

  public int MyProperty
  {
    get { return bindingSource.MyProperty; }
  }
   
  #region INotifyPropertyChanged Members

  public event PropertyChangedEventHandler PropertyChanged;

  #endregion
}

That works beautifully, but since it's specific to my particular object that's a lot of hand-coding. This whole proxy/adapter scheme screams for a generic implementation. But now we need to intercept requests of properties we may not know exist. Back in the perl days (and most dynamic languages feature this as well) I would have just created an AUTOLOAD method that catches all calls to methods that don't exist. It didn't seem like this would exist in C#, since that violates the whole compile time checking of a static language like C#. But there is Reflection, so maybe I was wrong. However, after checking with Oren Eini, who clearly has a much greater understanding of how to do funky things with C#, it turns out that such a facility indeed does not exist.

Next up was creating a proxy object that could be cast to the original type and handle the binding calls that way. I built a prototype based on Castle's Dynamic Proxy, which proxied the properties just fine, but apparently the event subscription doesn't work, because the proxy's PropertyChanged event never acquired any subscribers. So until I can figure out what happens to events on Dynamic Proxy, I'm stuck with statically built proxies.

In the meantime, I guess I'm going to look at BindingContext to see if the problem can be solved generically at that end, while trying to figure out why Dynamic Proxy isn't working. Stay tuned.

Labels: , , , , , ,