Monday, October 26, 2009

GetType From Referenced Assembly In Silverlight

I recently implemented a ValueConverter for our comboboxes in silverlight, whereby the translations for an enum would be shown as a list in the combobox, and when an item is selected, the value bound to the model would be whatever was described on the enumeration as the model value that gets persisted to the database (it’s a legacy database, so I couldn’t save the enumerated value on the model). Anyways, more on how that was done is for another blog post.

The converter gets an enumeration type as a converter parameter, so I needed to construct the type of enum at runtime (so I could get access the the enumerations that were defined, and the ModelValue attributes on each enumeration definition), since the converter should be able to handle any enumeration type that has been defined according to a specific convention. Trouble is, the enumerations were defined in a seperate silverlight assembly that was referenced from the client assembly, so I couldn’t just simply:

   1: Type type = Type.GetType("ClassLibrary1.Class1, ClassLibrary1");

… only if you specify the culture and the version in the above string parameter, will the type get returned, and since those change frequently, it wasn’t a practical solution.

So here’s helper method I wrote to get a type referenced in another assembly:

   1: public static Type GetAssemblyType(string assemblyName, string className)
   2: {
   3:     StreamResourceInfo info = Application.GetResourceStream(new Uri(assemblyName, UriKind.Relative));
   4:     Assembly assembly = new AssemblyPart().Load(info.Stream);
   5:     Type type = assembly.GetType(className);
   6:  
   7:     return type;   
   8: }

Usage:

… if you know the fully qualified class name and which assembly it’s in:

   1: Type type = GetAssemblyType("SilverlightClassLibrary1.dll", "SilverlightClassLibrary1.Class1");

… or if you only know the fully qualified class name, and don’t know which assembly it’s in:

   1: public static Type GetAssemblyType(string className)
   2: {
   3:     Type type = null;
   4:     foreach (AssemblyPart part in Deployment.Current.Parts)
   5:     {
   6:         type = GetAssemblyType(part.Source, className);
   7:         if (type != null)
   8:             break;
   9:     }
  10:     return type;
  11: }

usage:


   1: Type type = GetAssemblyType("SilverlightClassLibrary1.Class1");

Notice that in each case  that the class name that is specified is fully qualified with it’s namespace.


Happy Coding :)

6 comments:

Unknown said...

Thanks for the code. I've been having problems with this trying to write a string to type converter for Silverlight.

Claudio said...

Hi,

Thanks for the tip. It was very usefull in my case.
-Claudio

Richardson said...

Very nice post. Works fine in my application (SL4) to search types em WCF RIA Services metadata.

Unknown said...

Works great with SL4. I've been looking for this for hours. Thx a lot!

Simon said...

I had just embarked down this path and ran into this FileLoadException in my IValueConverter when trying to do a GetType with the enum typename and assembly name.

Like you, I have my types in another class library. Thanks for the workaround.

Do you have any idea on the efficiency of loading an assembly as a resource like this. Particularly since this is called everytime the value converter runs which could be a lot.

Malcolm Jack said...

@Simon - the cost is quite high if the call is being made iteratively. If you know the assembly name, then definitely use that method. What we ended up doing was add a caching broker between the classes that need the information and the implementation above - that way types are only loaded once per session. In the case of value converters, you may consider a static cache mechanism that is checked before using the GetType implementation above.