INotifyPropertyChanged with lambdas

There are several ways of implementing INotifyPropertyChanged in WPF applications.

One that I particularly like is by using PostSharp to implement INotifyPropertyChanged.

If you are not comfortable with PostSharp you can at least get rid of those nasty strings in standard implementation:

public class Model : ViewModeBase
{
    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            _status = value;
            OnPropertyChanged("Status");
        }
    }
};

Labda expressions look nicer and are easier to refactor:

public class MyModel : ViewModeBase
{
    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            _status = value;
            OnPropertyChanged(() => Status);
        }
    }
};

First thing we need to do is to create base class for all our ViewModels:

public class ViewModelBase
{
    public event PropertyChangedEventHandler PropertyChanged
        = delegate { };

    protected void OnPropertyChanged(
        Expression<func<object>> expression)
    {
        string propertyName = PropertyName.For(expression);
        this.PropertyChanged(
            this,
            new PropertyChangedEventArgs(propertyName));
    }
};

The implementation of PropertyName.For is very straightforward: How to get property name from lambda.

That’s it!
Nice, easy to refactor, compile-time checked INotifyPropertyChanged implementation.

How to get property name from lambda

The whole idea is simple, we want this test to pass:

[Test]
void CanGetPropertyName_UsingLambda()
{
  Assert.AreEqual("Name", PropertyName.For<person>(x => x.Name));
}

It seams nice and convenient way of getting property name.
Whole test fixture looks as follows:

[TestFixture]
public class PropertyNameTests
{
    public string NameForTest { get; set; }

    [Test]
    public void CanGetPropertyName_SameType_UsingLambda()
    {
        Assert.AreEqual("NameForTest",
            PropertyName.For(() => NameForTest));
    }

    [Test]
    public void CanGetPropertyName_UsingLambda()
    {
        Assert.AreEqual("Name",
            PropertyName.For<person>(x => x.Name));
        Assert.AreEqual("Age",
            PropertyName.For<person>(x => x.Age));
    }

    [Test]
    public void CanGetPropertyName_Composite_UsingLambda()
    {
        Assert.AreEqual("Home.City",
            PropertyName.For<person>(x => x.Home.City));
        Assert.AreEqual("Home.FlatNumber",
            PropertyName.For<person>(x => x.Home.FlatNumber));
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Home Home { get; set; }
}

public class Home
{
    public string City { get; set; }
    public string FlatNumber { get; set; }
}

Implementation uses .NET 3.5 feature called expression trees. Expression trees represent language-level code in the form of data. The data is stored in a tree-shaped structure.

/// <summary>
/// Gets property name using lambda expressions.
/// </summary>
internal class PropertyName
{
    public static string For<t>(
        Expression<func<t, object>> expression)
    {
        Expression body = expression.Body;
        return GetMemberName(body);
    }

    public static string For(
        Expression<func<object>> expression)
    {
        Expression body = expression.Body;
        return GetMemberName(body);
    }

    public static string GetMemberName(
        Expression expression)
    {
        if (expression is MemberExpression)
        {
            var memberExpression = (MemberExpression)expression;

            if (memberExpression.Expression.NodeType ==
                ExpressionType.MemberAccess)
            {
                return GetMemberName(memberExpression.Expression)
                    + "."
                    + memberExpression.Member.Name;
            }
            return memberExpression.Member.Name;
        }

        if (expression is UnaryExpression)
        {
            var unaryExpression = (UnaryExpression)expression;

            if (unaryExpression.NodeType != ExpressionType.Convert)
                throw new Exception(string.Format(
                    "Cannot interpret member from {0}",
                    expression));

            return GetMemberName(unaryExpression.Operand);
        }

        throw new Exception(string.Format(
            "Could not determine member from {0}",
            expression));
    }
}

UnaryExpression part is needed for value types to work.

Background processing in WinForms

Many times developing windows applications, you’ll need to perform some operations in background.

The problem you’ll face sooner or later is that those operations need to inform User Interface (UI) about their progress and completion.

UI doesn’t like to be informed about anything from a different thread: you’ll get nasty “Cross-thread operation not valid” exception from WinForms controls, if you try.

Let’s take a look at the sample Presenter code:

public void Start()
{
        TaskStatus taskStatus = this._backupService.CreateTask();
        taskStatus.Completed += BackupFinished;
        this._backupService.Start(taskStatus);
}

TaskStatus contains single event Completed.
What’ll do is that we’ll subscribe to this event to display some information on the View:

public void BackupFinished(object sender, EventArgs e)
{
        // If the operation is done on different thread,
        // you'll get "Cross-thread operation not valid"
        // exception from WinForms controls here.
        this.View.ShowMessage("Finished!");
}

So, what are the options:

Lets examine the last concept as SynchronizationContext is not a well-know-class in the .NET world.
Generally speaking this class is useful for synchronizing calls from worker thread to UI thread.

It has a static Current property that gets the synchronization context for the current thread or null if there is no UI thread (e.g. in Console application)

This is the TaskStatus class that utilizes SynchronizationContext.Current if it is not null:

public class TaskStatus
{
    private readonly SynchronizationContext _context;

    public event EventHandler Completed = delegate { };

    public TaskStatus()
    {
        _context = SynchronizationContext.Current;
    }

    internal void OnCompleted()
    {
        Synchronize(x => this.Completed(this, EventArgs.Empty));
    }

    private void Synchronize(SendOrPostCallback callback)
    {
        if (_context != null)
            _context.Post(callback, null);
        else
            callback(null);
    }
};

Now lets see some tests.

First we’ll check if the event is executed:

[Test]
public void Completed_RaisesCompleted()
{
    using(SyncContextHelper.No())
    {
        bool wasFired = false;
        TaskStatus status = new TaskStatus();
        status.Completed += (sender, args) => { wasFired = true; };
        status.OnCompleted();
        Assert.IsTrue(wasFired);
    }
}

The following test shows that in WindowsForms application, although operation is executed on different thread, Completed event is routed back (using windows message queue) to the UI thread:

[Test]
public void Completed_WithSyncContext_IsExecutedOnSameThread()
{
    using (SyncContextHelper.WinForms())
    {
         int completedOnThread = -1;
         int thisThread = Thread.CurrentThread.GetHashCode();

         TaskStatus status = new TaskStatus();
         status.Completed += (sender, args) =>
             {
                 completedOnThread =
                    Thread.CurrentThread.GetHashCode();
             };

         Scenario.ExecuteOnSeparateThread(status.OnCompleted);

         // process messages send from background thread
         // (like Completed event)
         Application.DoEvents();

         Assert.AreEqual(thisThread, completedOnThread);
    }
}

When there is no SynchronizationContext (SynchronizationContext.Current == null) Completed event is executed on the different thread:

[Test]
public void Completed_InMultiThreadedScenario_IsExecuedOnDifferentThread()
{
    using(SyncContextHelper.No())
    {
        int completedOnThread = -1;
        int thisThread = Thread.CurrentThread.GetHashCode();

        TaskStatus status = new TaskStatus();
        status.Completed += (sender, args) =>
            {
                completedOnThread =
                    Thread.CurrentThread.GetHashCode();
            };

        Scenario.ExecuteOnSeparateThread(status.OnCompleted);

        Assert.AreNotEqual(thisThread, completedOnThread);
    }
}

Finally unit test helper classes:

public class SyncContextHelper : IDisposable
{
    private readonly SynchronizationContext _previous;

    private SyncContextHelper(SynchronizationContext context)
    {
        _previous = SynchronizationContext.Current;
        SynchronizationContext.SetSynchronizationContext(context);
    }

    public static SyncContextHelper WinForms()
    {
        return new SyncContextHelper(
            new WindowsFormsSynchronizationContext());
    }

    public static SyncContextHelper No()
    {
        return new SyncContextHelper(null);
    }

    public void Dispose()
    {
        SynchronizationContext.SetSynchronizationContext(_previous);
    }
};

Testing DateTime.Now

When you are doing Test Driven Development (TDD) many time during the testing phase you’ll find yourself with a code that depends on current time.

It’s not possible write tests for this code as DateTime.Now changes constantly.

Let’s take a look at following method:

public string CreateName(...)
{
   return "name " + DateTime.Now;
}

The solution to this problem is simple. We’ll introduce Clock class with the same interface as DateTime:

public string CreateName(...)
{
   return "name " + Clock.Now;
}

We’d like the test to look something like this:

[Test]
public void CreateName_AddsCurrentTimeAtEnd()
{
    using (Clock.NowIs(new DateTime(2010, 12, 31, 23, 59, 00)))
    {
        string name = new ReportNameService().CreateName(...);
        Assert.AreEqual("name 2010-12-31 23:59:00", name);
    }
}

Tests should not leave any side effects. This is why we are using IDisposable pattern. After text execution Clock.Now is reverted and again returns current time.

Finally this is how Clock class looks like:

public class Clock : IDisposable
{
    private static DateTime? _nowForTest;

    public static DateTime Now
    {
        get { return _nowForTest ?? DateTime.Now; }
    }

    public static IDisposable NowIs(DateTime dateTime)
    {
        _nowForTest = dateTime;
        return new Clock();
    }

    public void Dispose()
    {
        _nowForTest = null;
    }
};

Mark emails as read using IMAP

In this article we’ll show how to mark emails as seen (read) using Mail.dll .NET IMAP library and IMAP protocol.

The following code connects to an IMAP server, finds unique ids of all unseen email messages and marks the first one as seen. Internally IMAP server uses IMAP flag \UNSEEN (Flag.Unseen) to remember which messages were already read by user.

// C# version

using(Imap imap = new Imap())
{
	imap.Connect("imap.example.com");    // or ConnectSSL for SSL
	imap.UseBestLogin("user", "password");

	imap.SelectInbox();
	List<long> uids = client.Search(Flag.Unseen);
	if (uids.Count > 0)
		client.MarkMessageSeenByUID(uids[0]);
    imap.Close();
}
' VB.NET version

Using imap As New Imap()
	imap.Connect("imap.example.com")    ' or ConnectSSL for SSL
	imap.UseBestLogin("user", "password")

	imap.SelectInbox()
	Dim uids As List(Of Long) = client.Search(Flag.Unseen)
	If uids.Count > 0 Then
		client.MarkMessageSeenByUID(uids(0))
	End If
	imap.Close()
End Using

If you are using GetMessageByUID to download email message or GetHeadersByUID to get only message headers, most IMAP servers will automatically mark such messages as seen. If it’s not expected behavior in your scenario, you can use Peek* methods: PeekHeadersByUID, PeekMessageByUID. Those methods in contrast to their Get* equivalents: GetMessageByUID and GetHeadersByUID do not set the Seen flag – emails are not marked as seen automatically.

You can also easily mark message as unseen by using Imap.MarkMessageUnseenByUID method.

Please note that it is not possible to mark messages as read using POP3 protocol. You can read more about differences between IMAP and POP3.