Of Static Code Analysis, CA0001, WinMD files and C# Dynamic in Metro Style apps

By jay at October 27, 2012 12:42 Tags: , , , ,

tl;dr: This article is about working around an FxCop internal bug using the C# dynamic keyword, not exactly the way is was supposed to be used.

 

With the release of Windows 8 and WinRT, developing in .NET requires adding references to the new WinMD file format.

This format is a .NET assembly look-alike, so look-alike that old ILDASM builds can open them.

These files are only containing stubs, the definition of types that come from WinRT, which is developed using native C++ code.

 

WinMD files and Static Code Analysis

FxCop is working rather fine with WinMD files in Metro style apps, except for one interest case, when compiling the following code :

private static void SomeMethod()
{
   var b = new Button();
   b.Command = null;
}

Which fails with the following exception when analyzed by FxCop, using the “Microsoft Managed Recommended Rules”:

CA0001 : Rule=Microsoft.Reliability#CA2002, Target=App.MainPage.#SomeMethod() : The following error was encountered while reading module 'App3': Could not resolve member reference: [Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null] Windows.UI.Xaml.Controls.Primitives.ButtonBase::put_Command.

The reason for this is rather obscure though. It seems that FxCop is trying to analyse the declarative security attributes of WinMD exposed methods, but fails to do so… Which is ironic since these attributes cannot be used in Metro style apps :) But still, this is a multi-framework analysis engine.

Unfortunately, there seem to be no way to put an ignore directive, or supression attribute for this kind of internal error so fixing this, until this gets resolved by Microsoft, requires a bit of a hack.

 

A CA0001 workaround and the Dynamic keyword

The problem here is that FxCop tries to analyze the code, and finds the put_Command() method and tries to analyse it. The goal here is to get the code compiled and executable, while having FxCop ignore it.

Here’s how to do it :

private static void SomeMethod()
{
   #if DEBUG
   var b = new Button();
   #else
   dynamic b = new Button();
   #endif

   b.Command = null;
}

I do agree with you, really. This is not a particularly pretty code, and may not be that fast to execute, but it does the trick to still have Static Code Analysis running to catch all other possible code issues.

Having a dynamic variable in Release configuration, where FxCop is executed, allows to hide the call to put_Command() as a string generated by the C# compiler, while maintaining it original meaning.

Here's what actually generated by the compiler, to evade FxCop scrutiny :

object b = new Button();
if (MainPage.o__SiteContainer0.<>p__Site1 == null)
{
   MainPage.o__SiteContainer0.<>p__Site1 = CallSite>.Create(Binder.SetMember(CSharpBinderFlags.None, "Command", typeof(MainPage), new CSharpArgumentInfo[]
   {
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null)
   }));
}
MainPage.o__SiteContainer0.<>p__Site1.Target(MainPage.o__SiteContainer0.<>p__Site1, b, null);

Having the code compiling using an actual static typing in Debug configuration leaves a bit of compile-time type checking, nonetheless.

There should be a connect entry for this soon, if you'd like to follow-up.

Happing dynamic hacking ! :)

blog comments powered by Disqus

About me

My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.