Overriding the default reflection behavior

One interesting capability of .NET 4.5 is that we can customize our reflection context, overriding the default reflection behavior with the CustomReflectionContext class.

With it, we can control what properties and attributes are exposed by a class through reflection.

How to do it...

Here we will override the reflection behavior to provide additional attributes:

  1. Create a new Visual Studio project of type Console Application named caOverridingReflection.
  2. In the References folder of the project, in the Solution Explorer, add a reference to the System.Reflection.Context assembly.
  3. Open the Program.cs file and add a using clause for system.reflection.
    using System.Reflection;
  4. Next, add the SomeClass declaration:
    class SomeClass
    {
        //Nothing here..
    }
  5. Then add a method to visualize, through reflection, the attributes of a type:
    public static void ShowAttributes(Type t)
    {
      foreach (Attribute a in t.GetCustomAttributes())
        {
          Console.WriteLine(a);
        }
        Console.ReadLine();
    }
  6. Call it from the Main method and the result should be none, that is, our class has no attributes so there is nothing to display on the console.
  7. Next, add a class with the name MyCustomReflectionContext.cs and add a reference to System.Reflection and System.Reflection.Context.
    using System.Reflection;
    using System.Reflection.Context;
  8. Change the generated code for the following one:
    class MyCustomReflectionContext :CustomReflectionContext
    {
      protected override IEnumerable<object> GetCustomAttributes(MemberInfo member, IEnumerable<object> declaredAttributes)
        {
          if (member == typeof(SomeClass)){
                List<object>CustomAttributes = new List<object>();
                CustomAttributes.Add(new DefaultMemberAttribute("One"));
               CustomAttributes.Add(new DefaultMemberAttribute("Two"));
               CustomAttributes.Add(new DefaultMemberAttribute("Three"));
    
          return base.GetCustomAttributes( member, declaredAttributes);
        }
    }
  9. Change the ShowAttributes method as follows:
    public static void ShowAttributes(Type t)
    {
    foreach (Attribute a in t.GetCustomAttributes())
        {
          Console.WriteLine(a + " - " + (a as DefaultMemberAttribute).MemberName );
        }
    Console.ReadLine();
    }
  10. Finally, change the code in the Main method as follows so that we can test it properly:
    static void Main(string[] args)
    {
    Console.WriteLine("1. Without Custom Reflection Context");
    ShowAttributes(typeof(SomeClass));
    
    Console.WriteLine("2. With Custom Reflection Context");
    MyCustomReflectionContextCustRefCtx = new MyCustomReflectionContext();
    Type Mappedtype = CustRefCtx.MapType(typeof(SomeClass).GetTypeInfo());
    ShowAttributes(Mappedtype);
    }
  11. If we execute the code, we will get the result shown in the following screenshot:
    How to do it...

How it works...

We used reflection to get the custom attributes of a type we just created and we got none.

Next, we created a CustomReflectionContext that will allow us to customize what is exposed through reflection. In our case, we are ensuring that if the class is our recently created class, it should return three DefaultMemberAttribute replies. If not, it will return the current attributes of the class.

To illustrate this reflection context, create an instance of the reflection context to map a concrete type, SomeClass in our case. We will now have this new mapped type created in the reflection context and thus affected by it.

Finally, we used reflection as we did previously but now we will get three new attributes that we did not get before.

There's more...

With .NET 4.5, we can customize the reflection output of types as we see fit, as it is able to provide virtualized type information. This can be useful in many situations when we want more flexibility in providing type-driven behaviors or to dynamically change the properties that we want to make available.

We had TypeDescriptors and PropertyDescriptors before but they were not really a solution for design time, which CustomReflectionContext is.

A smart application of this would be to get the MEF to compose types that aren't MEF-enabled (that is, decorated with the MEF attributes). When constructing catalogs specifying ReflectionContext, MEF will project types through that reflection context and use the resulting view for its composition mechanism.

Note

This next great application suggestion is from Mircea Trofin, from the CLR product team‑‑thanks, Mircea!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset