C# Corner

.NET 4.5 TypeInfo Reflection

The .NET 4.5 Framework includes some changes to the typical reflection use cases. Most importantly, the Type object has been split into two separate classes: Type and TypeInfo. Find out how and when to use each.

The .NET 4.5 Framework includes some changes to the typical reflection use cases. Most importantly, the Type object has been split into two separate classes: Type and TypeInfo. A TypeInfo instance contains the definition for a Type, and a Type now contains only reference data. If you're using reflection from within a .NET 4.5 Desktop or Web application, the old API is still available alongside the new API methods. Today I'll focus on how to use some of the key features of these new APIs available within a Windows Store application.

Type and TypeInfo Overview
The Type class provides a shallow view of an object's structure; a TypeInfo object represents the full definition of an object, including its relationship to its parent and child classes, if any. Furthermore, the Type API has been updated to return generic IEnumerable collections rather than generic array collections. This change could allow for the lazy traversal of a complex assembly via a custom reflection context. Mainly, the change allows for Type metadata to be traversed more easily via LINQ. Windows Store applications may only access the new IEnumerable collections.

Type API Changes
Let's look at some of the metadata that may be retrieved through Type without using TypeInfo, then dive into some of the TypeInfo API. The Type API allows for the retrieval of information about a type available to its calling assembly. This means you can get basic metadata such as the name, namespace, full name, module and so on. This is accomplished through the same API as in .NET 4.0. For example, to get the full name and namespace of a Type, you could do the following:

Type stringType = typeof(string);
string fullName = stringType.FullName;
string stringNameSpace = stringType.Namespace;

TypeInfo API
As you can see, Type offers a basic view of the structure of a class. If you want to dive a bit deeper into the structure of a class, you can use the new TypeInfo API. The TypeInfo definition of a Type is retrieved via the GetTypeInfo() method upon the Type object. Take a Person class, for example, that contains first and last name properties, a Modified event and a Save method:

public class Person 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public event EventHandler Modified;
    public void Save()
    {
        // save object to repository...
    }
}
Now, let's say you need to find out what properties, methods and events are defined on the Person class. This can be accomplished easily from a TypeInfo, via its DeclaredProperties, DeclaredMethods and DeclaredProperties:

TypeInfo personInfo = personType.GetTypeInfo();
IEnumerable<PropertyInfo> declaredProperties = personInfo.DeclaredProperties;
IEnumerable<MethodInfo> declaredMethods = personInfo.DeclaredMethods;
IEnumerable<EventInfo> declaredEvents = personInfo.DeclaredEvents;

Another common reflection task is to find all of the Types within an assembly. With the updated System.Reflection API, the Assembly class now returns a collection of TypeInfos rather than a Type array. For example, to get all the types defined in the running assembly, you can use the Assembly property from a retrieved TypeInfo definition. Then you'd access the DefinedTypes property on the Assembly instance:

Assembly myAssembly = this.GetType().GetTypeInfo().Assembly;
IEnumerable<TypeInfo> myTypes = myAssembly.DefinedTypes;

To get a better understanding of the new System.Reflection APIs, let's create a sample application that retrieves a list of all the defined types in the running assembly. When a Type is selected, its name, full name, declared properties, methods, and events are displayed.

Creating the Sample Application
To get started, create a new C# Windows Store application and add the Person class to the project, as shown earlier. Next, open up the MainPage.xaml file and add the XAML contained in Listing 1 as your root Grid element.

Now let's update the MainPage class to populate the list of defined types in the executing assembly. First, add a using statement for the System.Reflection namespace to the MainPage class. Then update the OnNavigatedTo method to retrieve the defined types for the application's assembly and bind it to the MyDefinedTypes ListView:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Assembly myAssembly = this.GetType().GetTypeInfo().Assembly;
    IEnumerable<TypeInfo> myTypes = myAssembly.DefinedTypes;
    MyDefinedTypes.DataContext = myTypes;
}
Now, all that's left is to wire up the SelectionChanged event of the MyDefinedTypes list view, and have the event handler bind the selected TypeInfo object to the TypeInfoDetails StackPanel control:

private void MyDefinedTypes_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.AddedItems.Count > 0)
    {
        TypeInfo selectedTypeInfo = e.AddedItems.First() as TypeInfo;
        TypeInfoDetails.DataContext = selectedTypeInfo;
        TypeInfoDetails.Visibility = Windows.UI.Xaml.Visibility.Visible;
    }
}
Your completed MainPage class should now look like Listing 2.

Congratulations! The sample application's completed (it should look like Figure 1), and you can reflect upon your accomplishment.


[Click on image for larger view.]
Figure 1. The completed application.

As you can see, there are some major changes to the Type class API if you're coming from past .NET Frameworks and looking to create a Windows Store App. Note that the new APIs are also available in .NET 4.5 Desktop and Web applications, as well as Portable Class libraries. I think the new APIs are cleaner, with their IEnumerable collections and division between reference and definition Type reflection usage.

About the Author

Eric Vogel is a Sr. Software Developer at Kunz, Leigh, & Associates in Okemos, MI. He is the president of the Greater Lansing User Group for .NET. Eric enjoys learning about software architecture and craftsmanship, and is always looking for ways to create more robust and testable applications. Contact him at vogelvision@gmail.com.

comments powered by Disqus

Reader Comments:

Tue, Dec 18, 2012 ConcernedCitizen USA

Seems like one more line of code is needed for completeness of the Person code example, immediately before the line: TypeInfo personInfo = personType.GetTypeInfo(); Where did personInfo come from, from typeof(Person), or from myPerson.GetType(), or...?

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.