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.
Here we will override the reflection behavior to provide additional attributes:
caOverridingReflection
.System.Reflection.Context
assembly.using
clause for system.reflection.using System.Reflection;
SomeClass
declaration:class SomeClass { //Nothing here.. }
public static void ShowAttributes(Type t) { foreach (Attribute a in t.GetCustomAttributes()) { Console.WriteLine(a); } Console.ReadLine(); }
Main
method and the result should be none, that is, our class has no attributes so there is nothing to display on the console.MyCustomReflectionContext.cs
and add a reference to System.Reflection
and System.Reflection.Context
.using System.Reflection; using System.Reflection.Context;
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); } }
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(); }
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); }
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.
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.