.NET Native behaves just like that expensive restaurant you love to got to: you have to wait until you finish the meal to see how much it will cost you - and it will definitely cost you!
Last weekend I was confronted with a bug in Cimbalino Toolkit MultiBindingBehavior, which caused apps using it to crash when they were built in Release mode!
I built a small test app and after a couple of minutes debugging it I noticed a MissingMetadataException getting raised; the culprit was found: .NET Native!
If you’re working with Universal Windows Apps (UWP) and don’t know what .NET Native is, I strongly advise you to start by reading the following excellent articles written by Morgan Brown, “a Software Development Engineer on the .NET Native team”:
Here’s the situation right now: when you build a UWP app, the compiler will do some “smart stuff” with your code (let’s skip the technicals here!), squeezing every little bit it can to make sure the compiled result will perform better and faster!
But there is a catch: if your code uses any type of dynamic coding features such as reflection or serialization, you might need to instruct the compiler that certain types in your application will be used as such, in order to avoid the exceptions like the MissingMetadataException
you see above.
To avoid such problems, you can add specially built rd.xml
files to your project - once again, check the articles above for more information on this subject!
The MultiBindingBehavior
works by using the AssociateObject
property value to reflect and dynamically create a binding expression, so what I needed was to ensure that it would be able to reflect any object passed to this property.
With this requirement in mind, I created a new Cimbalino.Toolkit.rd.xml
file, set its Build Action to Embedded Resource, and set the content to the following:
<?xml version="1.0" encoding="utf-8"?><Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"> <Library Name="Cimbalino.Toolkit"> <Type Name="Cimbalino.Toolkit.Behaviors.MultiBindingBehavior"> <Property Name="AssociatedObject" Serialize="Included" /> </Type> </Library></Directives>
Aaand… this didn’t work! I started getting a build error message stating that it couldn’t find any AssociatedObject
property in the Cimbalino.Toolkit.Behaviors.MultiBindingBehavior
.
Granted, the property does not exist directly in this class, but rather in the Behavior<T>
base class, so I guess one say that .NET Native compilation completely forgot a completely basic feature of .NET and most object oriented languages: Class Inheritance!
Taking this into account, I made a couple of changes in the file and here’s what in the end made it work:
<?xml version="1.0" encoding="utf-8"?><Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"> <Library Name="Cimbalino.Toolkit" /> <Library Name="Microsoft.Xaml.Interactions"> <Type Name="Microsoft.Xaml.Interactivity.Behavior{T}"> <Property Name="AssociatedObject" Serialize="Included" /> </Type> </Library></Directives>
So here’s what I learned in the past weekend:
- When working with Universal Windows Apps, make sure to build the app in Release mode and test it thoroughly!
- Keep an eye out on the build warnings for any problems with your
rd.xml
files. - If you’re working with MVVM or have Model representation classes, it might make sense to put these in a separate assembly, or at least in a separate namespace from the rest of the code - this will allow you to easily target these files in a
rd.xml
for .NET Native optimization exclusion.