I ran into this on the Win8 Developer’s Preview. I am porting over some Windows Phone Code. This code has a MEF/IOC-Like mechanism that let’s me do discovery on the project. The project itself is a simple App Framework; it has a bunch of content controls, but with the way it is configured you may decide that you don’t want to deploy all these controls, SO I needed to be able to discover controls and create them dynamically (the latter is what this tip is all about).
My original code looked like this:
public UserControl GetAndInitControlFor(string targetType, SectionInfo data)
{
UserControl result = null;
var typ = (from item in Catalog
where item.Key.Equals(targetType,
StringComparison.InvariantCultureIgnoreCase)
select item).FirstOrDefault();
if (!typ.Equals(null))
{
var ctor = typ.Value.GetConstructor(new Type[0]);
result = ctor.Invoke(new object[0]) as UserControl;
if (result != null )
{
((ISUAFContentControl)result).SetData(data);
}
}
return result;
}
This particular function looks up a control by it’s content type (a string) in the Dictionary that I have already built. If it finds a match then it takes the type instantiates it via the type’s constructor (essentially doing a “new” on the class). The only problem is that WinRT’s type doesn’t have a way to get the constructor. Instead there is a different mechanism you have to use.
Enter TypeInfo
I did some BINGing and I found the answer. There is a mechanism called TypeInfo. It’s apart of System.Reflection, so you will have to add a “Using System.Reflectiomn;” to the top of your file. Now you can get TypeInfo for you class. Here’s the rewritten function for WinRT:
public UserControl GetAndInitControlFor(string targetType, SectionInfo data)
{
UserControl result = null;
var typ = (from item in Catalog
where item.Key.Equals(targetType,
StringComparison.OrdinalIgnoreCase)
select item).FirstOrDefault();
if (!typ.Equals(null))
{
TypeInfo typeInfo = typ.Value.GetTypeInfo();
var ctor = typeInfo.DeclaredConstructors
.Where(c=>c.GetParameters().Count() == 0)
.Select(c=>c).FirstOrDefault();
result = ctor.Invoke(new object[0]) as UserControl;
if (result != null )
{
((ISUAFContentControl)result).SetData(data);
}
}
return result;
}
It’s very similar, but about midway down you can see where I create a TypeInfo for the type, and then using that type I have to write a Linq query to pull out the paramerless constructor that I am going to use to new up an instance.
I didn’t like having to change things, but I do like the new mechanism a lot better. These things should have been properties all along.