Xaml serialization quirks and gotchas

I recently had to build a little tool that would read its configuration from a XAML file (because XAML serialization is, most of the time, better and more customizable than standard XML serialization). The trick was that this tool had to be built on top of .NET 3.0 – not 3.5 or 4.0. And I discovered that there are a few little gotchas in .NET 3.0’s XAML serializer that I, somehow, never ran into before.

Gotcha #1: Automatic properties

Let’s say I wanted to deserialize the following class:

   1:      public class Foo
   2:      {
   3:          [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
   4:          public IList<int> Values { get; private set; }
   5:  
   6:          public Foo()
   7:          {
   8:              Values = new List<int>();
   9:          }
  10:      }

Pretty straightforward… however, if I try to deserialize it from a XAML file, I get the following exception:

property ‘Foo.Values’ cannot be set because it does not have an accessible set accessor. Line ‘3′ Position ‘4′.

I thought the framework was high on drugs or something, as what I wrote was pretty much the main use-case for the DesignerSerializationVisibility attribute. But then I remembered this other little gotcha with property reflection: when you use the auto-property syntax from C# 3.0 for a read-only property, the PropertyInfo you get on that property says you can write to it. This is because there is a setter method – only it’s private. And that’s why the XAML serializer complains about accessibility.

Note that this has been fixed with the new XAML serialization in .NET 4.0, with the new System.Xaml namespace. But if you need to target a previous version of the framework, you’ll need to refactor your code like so:

   1:      public class Foo
   2:      {
   3:          private List<int> mValues = new List<int>();
   4:  
   5:          [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
   6:          public IList<int> Values
   7:          {
   8:              get { return mValues; }
   9:          }
  10:          public Foo()
  11:          {
  12:          }
  13:      }

Gotcha #2: Public interface

Now you may think that the XAML serializer would be happy, but no… this is a very picky serializer! The next exception you get is:

‘Values’ is a read-only IEnumerable property, so ‘ConsoleApplication2.Foo’ must implement IAddChild. Line ‘3′ Position ‘4′.

That’s obviously weird, because the property is actually a list. But my guess is that the serializer is only looking for the ICollection interface. And the problem is that IList<T> does not implement that interface – it implements ICollection<T>, sure, but neither of those generic interfaces implement the “legacy” interfaces. That why most of the time you’re better off writing a proper collection class that inherits from Collection<T>, or some other base class from the System.Collections.ObjectModel namespace, because they implement both the generic and “legacy” interfaces… but sometimes you may not feel like writing an “IntCollection” class, right? Well. Life sucks.

Oh, and don’t bother actually implementing the IAddChild interface, or making the list itself implement that interface, it’s useless, you’ll get the same exception. That interface is some kind of weird leftover from the beta phase of WPF, and is now half-deprecated, half-internalized, as mentioned on that MSDN forums thread.

So basically, in our case, a quick fix would be changing the public interface to a List<int>.

After those few changes, the XAML serializer is happy and running fine!

Hope this helps.

Spam your friends with Yahoo! Pipes

You know how it goes: you’re an internet hipster with blogs and Twitter feeds and all that kind of new age stuff, but only other internet hipsters read them. Your friends (at least the ones that are not internet hipsters) only stick to Facebook. So how can you bring your stuff to them?

At first, it seems easy: Facebook can pull “stories” from various websites and services. Go to your profile, and under the status update box, click “Options” and then “Settings”. You get the following interface:

facebook_stories

That’s cool for most people. You bring in your Flickr photos, and your blog articles, and maybe a few other things… but what happens if you’ve got more than one blog? The “Blog/RSS” site can be only chosen once. Also, notice how you can choose Google Reader as a story source. Sure, this works, but the way your shared items appear on your wall is not optimal: they appear as “secondary activities”, presented like your comments or likes, sometimes merging several ones together which adds extra clicks to get to the actual article (e.g: “Ludovic shared 2 new items on Google Reader”, with only a link to your shared items page, which means you don’t know which 2 items were shared, as they may not be the last 2 ones if there have been other, newer ones since then). At least it was like that a few months ago (maybe they fixed it in the meantime, you tell me). That’s not proper spamming, so let’s do it the power user way.

A few years ago, Yahoo launched Yahoo! Pipes, a website that lets you build feed mashups. I decided to use that to aggregate all my stuff and post it on my Facebook wall.

It’s pretty simple, at first. You just go to the Yahoo! Pipes website, log-in, click “Create a pipe”, and add one source node for each site you want to pull data from. You’ll most probably use “Fetch Feed” nodes with the direct URL to your blogs and shared items RSS or Atom feeds, but you can also use some “Fetch Site Feed” nodes, too (they will find the actual feed URLs like any feed reader would do). Now pick the “Union” node from the “Operators” category, and plug all your sources into it. Plug the “Union” output into the “Pipe Output” node that should have been created by default for you. Voilà, you have an aggregated feed that you can import on your wall on Facebook!

pipe2

Or do you?

One problem you’ll notice right away is that all the items from the first feed are displayed, and then all the items from the second feed, and so on… The “Union” node only built a, well, union of those feeds. You need to re-order them by date so that all the items from all the sources are correctly mixed together. For this, add a “Sort” node, as shown above, that will sort items by “item.pubDate”.

There. Fixed? Nope… not yet.

Now you have a user experience problem. All those items appear as “notes” on your Facebook wall, with their contents directly readable. If you’re pulling feeds from your own websites and feeds from elsewhere at the same time (e.g. your Google Reader’s shared items feed), it becomes difficult for your friends to figure out which stuff was written by you, and which stuff is just cool shit you found on the web and wanted to share. You need to create a differentiator, like for example prepend “Shared on Google Reader:” in front of each of your shared items’ titles.

I’m still evaluating different options but at the moment I’m using something a bit less user-friendly, although definitely more friendly to the websites from which I share stuff from: I completely replace the contents of the item with a link to the actual article on its original website. This means that people can’t read the item right there (they need to click on the link), but it also means the people who posted the cool shit in the first place get a visitor that will potentially start clicking around on links and ads if he linked whatever I shared.

For this I created a different pipe, although I could have hard-coded it in the first one.

pipe

This pipe basically gets my Google Reader shared items feed and processes it in a loop: for each item, I replace the contents with a link whose text is just the title of the item. Inject this new pipe into the first one (you can reference a pipe inside another pipe) and, at last, you’re done!

The only problem I’ve had so far is that, after adding my aggregated feed to Facebook for the first time, the mobile version of the website did something funky. Instead of weaving all those notes into my friends’ timelines, moving the older items behind the more recent updates from other people and applications, it put everything it could at the top. So basically, I really spammed all my friends with dozens and dozens of items that were several weeks or even several months old. This bug didn’t affect the normal website, neither did it affect the iPhone application, as far as I could tell, so I only got a couple complaints. And hopefully they fixed the bug since then.

That’s pretty much it. You can find the 2 pipes I showed here and here.

About unit testing Maya and MStatus macros

Programmers in the video games and movies industry rarely write unit tests for all kinds of reasons and excuses, but every now and then, it happens. And it can get a bit complicated when you want to test a plug-in hosted by a 3rd party application like Autodesk’s Maya.

Setting up the unit test project

The good thing is, unlike most other 3d modeling packages, Maya comes with built in “batch” and “library” modes. The batch mode effectively runs Maya as a command line program, and the library mode allows you to host most of the Maya core engine inside your own application. This means that, as long as you’re not using anything that depends on the existence of the UI, it’s possible to run automated tests.

Once you’ve created your unit test project using your favourite test framework (lately I’ve been using boost::test), you want to initialize Maya in a minimalist environment (most probably in a test fixture setup phase). You can do that by pointing the MAYA_APP_DIR environment variable to a custom folder of your choice, which would contain a custom Maya.env file, along with maybe a few custom startup scripts. The goal is obviously to not load your complete production environment with all your 3rd party plug-ins. You also probably want to set the MAYA_PLUG_IN_PATH and MAYA_SCRIPT_PATH variables to point to the output or deployment folder(s) of your test project. This can even be done programmatically with the Maya API using MCommonSystemUtils::putEnv, as long as it happens before you initialize the engine.

When you’ve got the correct environment, you can call MLibrary::initialize and wait for an excruciatingly long time (somewhere between 20 and 30 seconds). Ideally, I’d like to start with a fresh Maya engine for each test suite (or even each test!), but given how long it takes for the library to initialize, that’s not an option and I do it only once on start-up. Between tests, I merely clear the scene with a “file -force –new” MEL command. I know you can severely strip down Maya by telling it to not even load the default plug-ins (e.g. if you’re testing something that doesn’t need rendering and animation and skinning and all that, you can in theory not load those features), but I haven’t bothered looking into that yet. If you have, I’d love to hear about it.

Anyway, all this, along with some nice helper functions for checking things in the scene, is pretty much enough to get you going… until you write your first “fail” test, i.e. a test that ensures that a given situation returns the expected error code or throws the expected exception.

The MStatus problem

You see, the problem is that, if you’re a bit paranoid like me, you’re probably using a lot of CHECK_MSTATUS macros around your code to make sure you’ll notice early if anything is not going as expected (the Maya API, being old as it is, doesn’t use exceptions, so if you don’t check return codes regularly you could go a long way with invalid objects, which increases the chances it’ll do some harm to your users’ data). When these macros are passed a non successful MStatus, they print a message to the standard error output. This pretty much means you’ll see that message printed in the terminal window as your unit test runs. That’s fine, but in the case of your fail test you don’t want that to happen because you only want to see unexpected error messages printed in the console.

Looking at the code for those CHECK_MSTATUS macros, one can see that they use the STL’s std::cerr to print the beginning of the message, and then call MStatus::perror to print a user-friendly description of the error. Being naive, I’m thinking “good, I just need to temporarily capture std::cerr!”. So I wrote the little following structure:

struct StreamCapture
{
public:
    StreamCapture(std::ostream& str, const std::ostream& replacement);
    ~StreamCapture();

private:
    std::ostream& mStr;
    const std::ostream& mReplacement;
    std::streambuf* mPrev;
};

StreamCapture::StreamCapture(std::ostream& str, const std::ostream& replacement) :
    mStr(str),
    mReplacement(replacement)
{
    mStr.flush();
    mPrev = mStr.rdbuf();
    mStr.rdbuf(mReplacement.rdbuf());
}

StreamCapture::~StreamCapture()
{
    mStr.flush();
    mStr.rdbuf(mPrev);
}
#define CAPTURE_COUT()\
    std::stringstream replace_cout_##__LINE__ ;\
    StreamCapture capture_cout_##__LINE__ (std::cout, replace_cout_##__LINE__)

#define CAPTURE_CERR()\
    std::stringstream replace_cerr_##__LINE__ ;\
    StreamCapture capture_cerr_##__LINE__ (std::cerr, replace_cerr_##__LINE__)

#define CAPTURE_ALL()\
    CAPTURE_COUT();\
    CAPTURE_CERR()

It’s using the classic RAII pattern, and you can use it as such:

BOOST_AUTO_TEST_CASE(TestThatSomethingFailingDoesntScrewUpTheRest)
{
    // Do something
    initializeStuff();
    {
        CAPTURE_ALL();
        callSomethingThatWillFail();
    }
    // Check that even with the failure, the data in the scene is still ok.
    checkStuff();
}

It won’t take you long to realize that only the first half of any error message printed by CHECK_MSTATUS has been captured. “No worries”, I thought. “They probably print the other half with a good ol’ fprintf, so I’ll capture stderr too!”.

Well… I tried a few different things, from a few different sources, but none of them worked. At best, it didn’t do anything – the error code description would still get printed. At worst, it would seemingly work but would then render the whole program unstable (most of the time it would crash on the second attempt to capture the error output). I don’t know what Maya is using to print that MStatus out, but it sure isn’t a straightforward fprintf.

Now, before moving on to my (somewhat disappointing) solution, let’s look at another MStatus problem.

The CHECK_MSTATUS_AND_RETURN_IT problem

One of the CHECK_MSTATUS macros is CHECK_MSTATUS_AND_RETURN_IT, which checks for any error and, if found, will make the current function return that very same error. A typical use of it would be:

MStatus doSomethingSimple();

MStatus doSomethingMoreComplicated()
{
    // Do stuff
    CHECK_MSTATUS_AND_RETURN_IT(doSomethingSimple());
    // Do more stuff
    return MStatus::kSuccess;
}

The problem is that this macro is implemented as such:

#define CHECK_MSTATUS_AND_RETURN_IT(_status)\
    CHECK_MSTATUS_AND_RETURN((_status), (_status))

Do you see? It calls CHECK_MSTATUS_AND_RETURN which, if the first status is an error, returns the second status. This means that if the call to doSomethingSimple fails, the macro will call it a second time to get the return value!

This is obviously bad… (and another example of why C++ macros can be evil because it’s not obvious what you can and cannot pass into them).

At first I defined a CHECK_MSTATUS_AND_RETURN_IT_SAFE macro that did the correct thing, but for various reasons I decided to just redefine the original macro and prevent other programmers from making that mistake (at least as long as the my header file was included, which is easier to enforce, especially if you’re using things like pre-compiled headers):

#pragma warning(push)
#pragma warning(disable:4005)
#define CHECK_MSTATUS_AND_RETURN_IT(status)\
    CHECK_MSTATUS_AND_RETURN_IT_SAFE(status);
#pragma warning(pop)

Back to the MStatus problem

Now what does this have to do with the error message problem?

Well, now that I was already redefining one of the CHECK_MSTATUS macros, I figured it wasn’t much more trouble to redefine them all (there’s only a handful of them). The only thing you need to do is replace the call to MStatus::perror with a line that sends the MStatus into std::cerr. I mean, MStatus already has operator<< defined for IO streams, so it’s not like I had to do anything more than some copy/paste and changing one line.

So there you have it: my crappy solution for having clean Maya unit tests was to redefine the CHECK_MSTATUS macros so they use the STL’s IO streams. Do you have a better or more elegant solution? I’d love to know about it!

Writing a custom Main() method for WPF applications

Creating a new WPF project in Visual Studio gives you the following pretty simple application markup and code:

<Application x:Class="WpfApplication2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
</Application>
namespace WpfApplication2
{
    public partial class App : Application
    {
    }
}

Understanding how it really works, and how to supply your own custom Main() method, is just a search query away. You basically need to change the application’s build action from “Application Definition” to “Page”, create a constructor that calls “InitializeComponent”, and write your Main() by eventually calling one of the application’s “Run” method overloads.

wpf_app

namespace WpfApplication1
{
    public partial class App : Application
    {
        App()
        {
            InitializeComponent();
        }

        [STAThread]
        static void Main()
        {
            Window1 window = new Window1();
            App app = new App();
            app.Run(window);
        }
    }
}

Don’t forget, also, to remove the “StartupUri” from the App.xaml, otherwise another copy of window will show up (unless you get an error because the URI points to a non existing XAML resource).

What most articles won’t tell you, though (some of them actually getting it wrong), is that it’s important that you create the application before you create your first window. To illustrate this, let’s add an application resource to App.xaml:

<Application
    x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Red" />
        </Style>
    </Application.Resources>
</Application>

It’s a style that makes buttons red. Since it’s defined at application level, all buttons in all the windows should be red (except those that define their own local style override). For example, here’s the markup for my Window1:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Button>Is This Red?</Button>
    </Grid>
</Window>

We should see a window with a red button in it. But when I run the project, I get this:

not_red

Well… it’s not red.

The issue is that the window is created before the application. This means that when it queries the current application to get the globals resources, it finds nothing. What you need to do is simply create the application first:

[STAThread]
static void Main()
{
    App app = new App();
    Window1 window = new Window1();
    app.Run(window);
}

By simply switching those two lines, you get the expected result:

red

This drove me crazy for an hour or so – I thought there was something funky going on with my theme management code or something. Hopefully this will save someone some pain.

Visual Studio Express’ limitations lead to bad practices

Visual Studio Express only has a subset of what you can find in Visual Studio Professional, which makes complete sense, but two missing features actually prevent users from following best programming practices in my opinion. The whole point of Express is to let enthusiasts and students discover the joys of programming – so we might as well let them do it the proper way.

Continue reading “Visual Studio Express’ limitations lead to bad practices”

My home media & entertainment setup

I was working on this article when I spotted that my friend Bertrand Le Roy posted on that very same subject so I’ll turn this into a reply to his. The new year seems like a good time for bragging about one’s home video setup, it seems.

First, you may notice that my setup is quite simple because I don’t have any audio gear. Yet. That’s because until recently, my apartments were too small for me to have any decent speakers.

Home Theatre PC (XBMC Dashboard)

Continue reading “My home media & entertainment setup”

Exposing global variables in IronPython

Lately I’ve been playing around a bit with IronPython and how to embed it inside an application to add scripting features. I’m still figuring things out, but I had a hard time exposing global variables to the Python environment.

The idea was to expose a couple of .NET objects (mainly a few important managers/singletons from the app’s API) as global variables so that scripts could access and act on the important parts of the app (query the database, batch run actions, etc.).

At first, I exposed some objects as variables of my ScriptScope:

public void SetupScope(ScriptScope scope)
{
    scope.SetVariable("test_string", "This is a test string");
    scope.SetVariable("test_callback_method", new Action(TestCallbackMethod));
    scope.SetVariable("test_callback_function", new Func<string, string>(TestCallbackFunction));
}

The problem was that only interactive scripting would get access to those variables (I had a simple UI for typing commands to be executed on that ScriptScope). Using “test_string” in a function loaded from a module would result in a “name ‘test_string’ is not defined” error. Using either “import” or “global” would not fix it.

Continue reading “Exposing global variables in IronPython”

Some more contacts love

There’s been a lot of improvement in communications in the past few years, from better services to brand new ones, but I still feel like contact management is lagging behind. I mean, isn’t it important to be able to find how to contact somebody in the first place?

Here are a few things I think could be better.

Continue reading “Some more contacts love”