Notes from Daily Encounters with Technology RSS 2.0
 
# Thursday, April 10, 2014

On Wednesday I had my only session at the spring NT conference in Bled this year. I was speaking about the new stuff for developers in Windows 8.1 Update. After a short mention of the universal project, I focused on the changes available only to sideloaded enterprise applications.

Given the small amount of time available for preparing the session, I didn’t prepare any examples of my own and used the publicly available ones from Microsoft instead. As always, you can download my slides from SlideShare.

Apart from the links at the end of the slide deck, keep an eye on Harry Pierson’s blog. He had a session on this subject at Build and his blog is currently probably the best source of information about it.

Thursday, April 10, 2014 9:13:38 PM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | C# | Metro | Windows Store | Downloads | Presentations
# Monday, March 31, 2014

Recently a colleague of mine mentioned that he has just learned about KeyedByTypeCollection, although it has been included with .NET framework since .NET 3.0. I’m writing this post, because I didn’t know about it until that day, either. This leads me to believe that there must be many more developers out there who aren’t aware of this niche class being readily available.

Unlike other generic collections, it provides a simple way of storing objects of multiple different types in a single collection, still being able to retrieve them in a strongly typed manner. Admittedly, it’s not a common requirement, but there are scenarios in which such a functionality is extremely useful and having a class for it in .NET framework is really nice. Let me present two such scenarios that have come up in my daily work lately.

Designing a data access layer usually also means creating a data context or repository service class, which provides access to repositories of different entity types. This could be a typical repository service interface:

public interface IRepositoryService
{
    IRepository<Player> Players { get; }
    IRepository<Game> Games { get; }
    IRepository<Session> Sessions { get; }
    IRepository<Round> Rounds { get; }
}

Instead of having a separate private field for each entity repository, they can all be stored in a KeyedByTypedCollection and retrieved from it in individual properties:

private KeyedByTypeCollection<object> _repositories;

public IRepository<Player> Players
{
    get
    {
        return _repositories.Find<IRepository<Player>>();
    }
}

This makes it really easy to implement a generic method for accessing repositories based on their entity type, alongside the strongly typed properties or even instead of them:

public IRepository<T> GetRepository<T>()
{
    return _repositories.Find<IRepository<T>>();
}

In Workflow Foundation extensions can be used to provide additional functionalities when hosting workflows, either to activities or during the persistence process. The IWorkflowInstanceExtension interface allows individual extensions to return additional extensions, they require to function correctly.

The handling of these extensions can again be internally implemented very elegantly using a KeyedByTypeCollection:

private KeyedByTypeCollection<object> _extensions = new KeyedByTypeCollection<object>
{
    new PersistenceExtension(),
    new ActivityExtension()
};

public IEnumerable<object> GetAdditionalExtensions()
{
    return _extensions;
}

public void UseIndividualExtensions()
{
    var persistenceExtension = _extensions.Find<PersistenceExtension>();
    var activityExtension = _extensions.Find<ActivityExtension>();
}

Both of the above examples could of course just as well be implemented without KeyedByTypeCollection, but it wouldn’t be as elegant and it would require more code. As I often say, know the tools you are using, .NET framework base class library in this case.

Monday, March 31, 2014 5:04:03 AM (Central European Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
Development | .NET | WF4
# Monday, March 24, 2014

A great side effect of view models being implemented in portable class libraries when using MvvmCross, is the ability to unit test them on any platform, not necessarily the one you are targeting. So even when developing a mobile application, you can test it in full .NET framework and take advantage of all the tooling available there. In my opinion NCrunch test runner and Moq mocking framework are great examples of tools that are not available for mobile platforms but can make testing much more pleasant.

View model unit tests often depend on PropertyChanged events or have to test them. A typical simple view model unit test checking whether data gets loaded correctly on Start, could look like this:

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);

    var handle = new AutoResetEvent(false);
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == "Players")
        {
            handle.Set();
        }
    };
    viewModel.Start();
    Assert.IsTrue(handle.WaitOne(TimeSpan.FromMilliseconds(50)));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

Contrary to what you would expect, the above test fails because the PropertyChanged event is never raised, even though the view model being tested, works correctly.

After taking a look at MvxNotifyPropertyChanged code, it was easy to explain the behavior. RaisePropertyChanged by default marshals PropertyChanged events to the UI thread (see ShouldAlwaysRaiseInpcOnUserInterfaceThread):

public virtual void RaisePropertyChanged(PropertyChangedEventArgs changedArgs)
{
    // check for interception before broadcasting change
    if (InterceptRaisePropertyChanged(changedArgs)
        == MvxInpcInterceptionResult.DoNotRaisePropertyChanged)
        return;

    var raiseAction = new Action(() =>
            {
                var handler = PropertyChanged;

                if (handler != null)
                    handler(this, changedArgs);
            });

    if (ShouldAlwaysRaiseInpcOnUserInterfaceThread())
    {
        // check for subscription before potentially causing a cross-threaded call
        if (PropertyChanged == null)
            return;

        InvokeOnMainThread(raiseAction);
    }
    else
    {
        raiseAction();
    }
}

In unit tests there’s no Dispatcher set, causing InvokeOnMainThread not to raise the event at all:

protected void InvokeOnMainThread(Action action)
{
    if (Dispatcher != null)
        Dispatcher.RequestMainThreadAction(action);
}

Fortunately the problem is really to fix now, with all the information at hand. There’s no need to marshal the events to UI thread in unit tests, therefore the corresponding view model setting can be disabled (notice the call to ShouldAlwaysRaiseInpcOnUserInterfaceThread(false)):

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);
    viewModel.ShouldAlwaysRaiseInpcOnUserInterfaceThread(false);

    var handle = new AutoResetEvent(false);
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == "Players")
        {
            handle.Set();
        }
    };
    viewModel.Start();
    Assert.IsTrue(handle.WaitOne(TimeSpan.FromMilliseconds(50)));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

With this minor modification the unit test succeeds as expected.

There’s still quite a lot of code involved in setting up the handling of PropertyChanged event in the unit test. Since a similar pattern is often required in tests, it can be wrapped in an extension method to make the tests more straightforward and less repetitive:

public static Task WaitPropertyChangedAsync(this MvxViewModel viewModel, string propertyName)
{
    viewModel.ShouldAlwaysRaiseInpcOnUserInterfaceThread(false);

    var task = new Task(() => { });
    viewModel.PropertyChanged += (sender, args) =>
    {
        if (args.PropertyName == propertyName)
        {
            task.Start();
        }
    };
    return task;
}

Now the unit test can be much simpler and will only contain the code actually relevant to it:

[TestMethod]
public void LoadsPlayersOnStartAndNotifies()
{
    var expected = new[]
    {
        new Player(),
        new Player(),
        new Player()
    };

    var repositoryServiceMock = new Mock<IRepositoryService>();
    repositoryServiceMock.Setup(mock => mock.GetPlayers()).Returns(expected);
    var viewModel = new PlayersEditorViewModel(repositoryServiceMock.Object);
    var propertyChangedTask = viewModel.WaitPropertyChangedAsync("Players");

    viewModel.Start();
    Assert.IsTrue(propertyChangedTask.Wait(50));

    CollectionAssert.AreEqual(expected, viewModel.Players);
}

Monday, March 24, 2014 6:37:58 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | MvvmCross | Testing
# Monday, March 17, 2014

Certain aspects of Workflow Foundation are still poorly documented; the persistence framework being one of them. The following snippet is typically used for setting up the instance store:

var instanceStore = new SqlWorkflowInstanceStore(connectionString);
instanceStore.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
var instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;

It’s difficult to find a detailed explanation of what all of this does; and to be honest, usually it’s not necessary. At least not, until you start encountering problems, such as InstanceOwnerException: The execution of an InstancePersistenceCommand was interrupted because the instance owner registration for owner ID '9938cd6d-a9cb-49ad-a492-7c087dcc93af' has become invalid. This error indicates that the in-memory copy of all instances locked by this owner have become stale and should be discarded, along with the InstanceHandles. Typically, this error is best handled by restarting the host.

The error is closely related to the HostLockRenewalPeriod property which defines how long obtained instance handle is valid without being renewed. If you try monitoring the database while an instance store with a valid instance handle is instantiated, you will notice [System.Activities.DurableInstancing].[ExtendLock] being called periodically. This stored procedure is responsible for renewing the handle. If for some reason it fails to be called within the specified HostLockRenewalPeriod, the above mentioned exception will be thrown when attempting to persist a workflow. A typical reason for this would be temporarily inaccessible database due to maintenance or networking problems. It’s not something that happens often, but it’s bound to happen if you have a long living instance store, e.g. in a constantly running workflow host, such as a Windows service.

Fortunately it’s not all that difficult to fix the problem, once you know the cause of it. Before using the instance store you should always check, if the handle is still valid; and renew it, if it’s not:

if (!instanceHandle.IsValid)
{
    instanceHandle = instanceStore.CreateInstanceHandle();
    var view = instanceStore.Execute(instanceHandle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
    instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}

It’s definitely less invasive than the restart of the host, suggested by the error message.

Monday, March 17, 2014 4:31:30 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | .NET | C# | WF4
# Monday, March 10, 2014

Take a close look at the following piece of code:

String String = "";

var strTest = "TEST";
Console.Write(String.Format(strTest));

dynamic dynTest = "TEST";
Console.Write(String.Format(dynTest));

Think about it for a minute and try answering the following questions:

  • Is it going to compile without errors?
  • Is it going to run without errors?
  • What will the output be?

Feel free to open Visual Studio and compile the code, but do try answering the questions first.

Here are the correct answers for those of you who believe me without testing it your self – the code will compile, but it will throw a runtime exception at the last line: Member 'string.Format(string, params object[])' cannot be accessed with an instance reference; qualify it with a type name instead.

Why does the error happen? Let’s take a look at how .NET Reflector decompiles the above code:

string str = "";
string format = "TEST";
Console.Write(string.Format(format, new object[0]));
object obj2 = "TEST";
Console.Write(str.Format((dynamic) obj2));

That makes it much clearer, doesn’t it?

  • In the first case Format is called on the string type as expected.
  • In the second case Format is called on the local instance of string. Since there is no instance method on string type named Format and since C# doesn’t allow calling static methods with an instance reference, this results in a runtime error.

Obviously, the compiler doesn’t bind that second call as one would naively expect. Even worse; Visual Studio interprets the code differently than the compiler: in IDE String in the second call is shown as the type, not the variable.

Of course, the behavior can be explained, no matter how unintuitive it is. C# language specification comes to the rescue. Let’s start with a quote from section 7.2: Static and Dynamic Binding:

However, if an expression is a dynamic expression (i.e. has the type dynamic) this indicates that any binding that it participates in should be based on its run-time type (i.e. the actual type of the object it denotes at run-time) rather than the type it has at compile-time. The binding of such an operation is therefore deferred until the time where the operation is to be executed during the running of the program. This is referred to as dynamic binding.

In our example dynTest is a dynamic expression, therefore it makes String.Format binding dynamic as well. This explains, why the exception is thrown at runtime.

Still, why does it work correctly in the first case? While I’m pretty sure the answer to this question can be found in the language specification as well, it is much better described in Eric Lippert’s blog post:

So the reason that the compiler does not remove static methods when calling through an instance is because the compiler does not necessarily know that you are calling through an instance. Because there are situations where it is ambiguous whether you’re calling through an instance or a type, we defer deciding which you meant until the best method has been selected.

That’s the case for the first call in our example. String is ambiguous and could be both a local variable or a type. The compiler correctly selected the static method as the best candidate function member. In the second case the binding has been postponed till runtime, and the best candidate function member hasn’t been selected at all. Therefore the compiler decided that String is a local variable name, causing the runtime binding to fail because the best candidate function member is static and can’t be called with the instance reference of the local variable. Mystery solved.

If you haven’t done so already, do read the above mentioned Eric Lippert’s blog post; it is well worth your time and will give an even better insight into binding.

Monday, March 10, 2014 6:48:23 AM (Central European Standard Time, UTC+01:00)  #    Comments [0] - Trackback
Development | C#
My Book

NuGet 2 Essentials

About Me
Currently Reading

Xamarin Mobile Application Development for Android

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

All Content © 2014, Damir Arh, M. Sc. Send mail to the author(s) - Privacy Policy - Sign In
Based on DasBlog theme 'Business' created by Christoph De Baene (delarou)
Social Network Icon Pack by Komodo Media, Rogie King is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.