Friday, October 02, 2009

Very often we here at OpenNETCF work on projects that are internal to companies that is seen by relatively few people or we do infrastructure work that helps an app succeed, but it isn't the app itself. Sometimes, though, we do get an opportunity to write public, commercial applications.  We've just finished version 1 of Trapster for Windows Mobile, which chould hit the Windows Marketplace this month.  For more info on what Trapster is and how it works visit their website, or read one of their reviews such as that on PocketNow or CNET.

The pieces of note here are that we used the OpenNETCF IoC Framework for dependency injection and the Bing Maps web services for all of the mapping and navigation work.

10/2/2009 8:58:57 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Monday, August 31, 2009

Today I came back to a project that I hadn't worked on in a few months.  I got latest from source control and tried to build, and the linker complained "Error 1 fatal error LNK1104: cannot open file 'secchk.lib' AudioControl AudioControl".

Now WTF?  I knew this was working before.  The error remindinded me vaguely of a previous problem I had, so I searched my blog and found this one.  The problem that time was that I was building for PPC03 and the project for some reason had not added secchk.lib to my platform.  THis time, however, I am building for a generic Windows CE device, and for some reason it *is* adding it.  Well CE doesn't have this lib, and I don't want it.  A quick scan through the project settings didn't turn up anything obvious, so I went with the more heavy-handed approach of adding the following to a common header file:

#pragma comment(linker, "/nodefaultlib:secchk.lib")
#pragma comment(linker, "/nodefaultlib:ccrtrtti.lib")

Done and done.  (the second is required because when you add the first and rebuild, the linker will then complain about not finding ccrtrtti.lib). No idea why I get the error (I'd love to know the root cause) but I don't have time to dig around.  Fortunately the #pragma directive overrides whatever project settings you have, which can be handy at times.

8/31/2009 10:11:28 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Wednesday, August 26, 2009

I've pushed another ode update for the OpenNETCF IoC Framework into Codeplex.  Highlights in this one are the fact that I've added a WorkItems collection to the WorkItem class, meaning there's now the potential for parent/child relationships.

8/26/2009 9:11:29 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Friday, August 14, 2009

Consider the following code:

public class MyAttribute : Attribute
{
  public MyAttribute(UnmanagedType foo)
  {
  }

  public int Bar { get; set; }
}

[StructLayout(LayoutKind.Sequential)]
public struct Test
{
  [CLSCompliant(false)]
  [MyAttribute(UnmanagedType.ByValArray, Bar = 4)]
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  public ushort[] ArrayShorts;
}

class Program
{
  static void Main(string[] args)
  {
    FieldInfo field_info = typeof(Test).GetField("ArrayShorts");
    object[] custom_attributes = field_info.GetCustomAttributes(typeof(MarshalAsAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
    custom_attributes = field_info.GetCustomAttributes(typeof(MyAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
    custom_attributes = field_info.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
  }
}

The code defines a custom attribute, then defices a struct that uses that attribute, along with some BCL-provided attributes.  It then uses reflection to get back those attributes. What would you expect the output to be?  Probably this:

Attributes: 1

Attributes: 1

Attributes: 1


And if you run it against the full framework, that's exactly what you get.  But if you run it against the Compact framework, you instead get this:

Attributes: 0

Attributes: 1

Attributes: 1

Yes, you're seeing it correctly, the MarshalAsAttribute doesn't show up.  So immediately I call this a bug since the frameworks differ and there is no documentation that says they should (even if it were documented I'd call it a bug).  So I did a little asking around and a little research.  It turns out that there is a difference between MarshalAs and the other attributes.  According to the ECMA-335 spec for the Common Language Interface, section 21.2

There are two kinds of custom attributes, called genuine custom attributes, and pseudo custom attributes.

Custom attributes and pseudo custom attributes are treated differently, at the time they are defined, as follows:

  • A custom attribute is stored directly into the metadata; the‘blob’ which holds its defining data is stored as-is. That ‘blob’ can be retrieved later.
  • A pseudo custom attribute is recognized because its name is one of a short list. Rather than store its ‘blob’ directly in metadata, that ‘blob’ is parsed, and the information it contains is used to set bits and/or fields within metadata tables. The ‘blob’ is then discarded; it cannot be retrieved later.

The spec goes on to say that the MarshalAsAttribute is a pseudo custom attribute, so it would fall into the second bullet above.  If you re-read the last sentence in that bullet  you'll see that "it cannot be retrieved later."  So, in fact, it seems like the full framework is the one in error here, at least per the spec! This attribute should not be readable at all at run time.

Now why the authors of the spec would have made such a strange exception is beyond me.  THe method in the language is clearly called GetCustomattributes, not "GetOnlySomeCustomAttributes" and this is the first I've even heard of pseudo cutom attributes, which tells me it's not well documented and likely not well known.  So while the Compact Framework follows the spec to the letter, if you go with reasonable expectations as a guideline, I'm going to have to say that it's behavior is wrong and that the spec is incorrect and needs revising.

8/14/2009 11:15:23 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Wednesday, July 15, 2009

I've been using the OpenNETCF IoC framework for several new projects lately, and I really like it.  I think my favorite feature is the fact it gives you the ability to subscribe to events from other objects without requiring an instance of the event publisher.  In fact you don't even need to know the publishers type or even of its existence - you simply need to know the name of the event that might get raised.

The only downside I've hit lately is that the performance for creating objects is not fantastic.  Of course that's to be expected.  To achieve all of this really loosely coupled architecture, we have to rely heavily on Reflection.  Not only do we have to do object creation through Reflection, but we have to do a lot of complex querying looking for type names and attributes, and this can take a while.

In an effort to improve things a bit, I'm working on updating the internal ObjectFactory class that is responsible for all of this heavy lifting.  I've added caches for most of the items that get queried through Reflection.  For example now when we want to find all of the published events from a specific Type, we use reflection the first time, but every subsequent time we pull the list from a cache.

A unit test for creating a single object that both publishes and subscribes to events yields nearly a 5,000% improvement in creating speed for the second object of the same type.  Yes, you read that right - it is 50 times faster creating the exact same object type the second time around.  There's no avoiding the pain the first time we have to inspect a Type, but I've already noticed a marked improvement in app startup time using the new changes.

7/15/2009 1:27:27 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  |