65.9K
CodeProject is changing. Read more.
Home

Puresharp Reflection API .NET 4.0+ for Safer Reflection Usage

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.24/5 (9 votes)

Jun 4, 2017

CPOL

2 min read

viewsIcon

9588

Puresharp Reflection API .NET 4.0+ provides a way to use Reflection without defining string constants to get metadatas based on linq expressions & lambda expressions.

Introduction

Reflection API is very powerful. It provides a way to analyse code at runtime and offer a lot of features to increase productivity by suppressing a lot of boilerplate code. On another hand, Reflection API can introduce a lot of exceptions at runtime and can make an application very difficult to evolve.

Common Usage of Reflection

Reflection provides metadatas to describe your source code:

  • System.Type
  • System.Reflection.Assembly
  • System.Reflection.MemberInfo
  • System.Reflection.FieldInfo
  • System.Reflection.MethodBase
  • System.Reflection.ConstructorInfo
  • System.Reflection.MethodInfo
  • System.Reflection.PropertyInfo
  • System.Reflection.ParameterInfo
  • ...

I will not describe all these metadata because you can find the full documentation on MSDN.

Example of Reflection Usage

  • typeof keyword allows you to get System.Type object containing all your needs to instrospect a type.
    Type type = typeof(object);
  • from a type, you can get members:
    Type type = typeof(object);
    MethodInfo method = typeof(object).GetMethod("GetHashCode");
    ConstructorInfo constructor = typeof(object).GetConstructor(Type.EmptyTypes);

Why Is It An Issue to Use It Like This?

The typeof keyword is not bad because it is checked at compile time, but GetMethod, GetField, GetProperty & GetConstructor can introduce runtime error and make a program harder to evolve. Indeed, if you change a method name or field name, your reflection will fail even if it worked before. It means that you have to be careful in each reflection usage when the program changes.

What Can I Do to Avoid These Issues?

Just avoid Reflection if you can. Indeed, if the cost of the program without reflection is not too heavy to handle, do it. Fortunately, generics can help a lot to do it. But in some cases, it is really more productive to introduce reflection into the program. That's why Puresharp Reflection API .NET 4.0+ can help you to make your reflection usage safer.

Puresharp Reflection API

Puresharp Reflection API .NET 4.0+ is a set of classes allowing safer Reflection usage using linq & lambda expressions. It provides API to get static and instance metadatas and is materialized as nuget package:

The principle is simple, you just have to express your metadata using lambda expression compatible for linq expression.

Use cases: Each Case Compares Standard Reflection vs Puresharp Reflection

  • Fast access to type by using generic type cache:
    Type type = typeof(object);
    Type type = Metadata<object>.Type;
  • Get constructor of a type:
    ConstructorInfo constructor = typeof(Uri).GetConstructor
                                  (new Type[] { typeof(string) }); //standard
    ConstructorInfo constructor = Metadata.Constructor(() => new Uri(Argument<string>.Value));
  • Get static field:
    FieldInfo field = typeof(Uri).GetField("SchemeDelimiter");
    FieldInfo field = Metadata.Field(() => Uri.SchemeDelimiter);
  • Get static method:
    MethodInfo method = typeof(object).GetMethod("ReferenceEquals", 
                        new Type[] { typeof(object), typeof(object) });
    MethodInfo method = Metadata.Method(() => 
        object.ReferenceEquals(Argument<object>.Value, Argument<object>.Value));
  • Get static property
    PropertyInfo property = typeof(AppDomain).GetProperty("CurrentDomain");
    PropertyInfo property = Metadata.Property(() => AppDomain.CurrentDomain);
  • Get instance field
    public class MyClass
    {
        public int MyField;
    }
    FieldInfo field = typeof(MyClass).GetField("MyField");
    FieldInfo field = Metadata<MyClass>.Field(myClass => myClass.MyField);
  • get instance method
    MethodInfo method = typeof(DateTime).GetMethod("Add", new Type[] { typeof(TimeSpan) });
    MethodInfo method = Metadata<DateTime>.Method
                 (datetime => datetime.Add(Argument<TimeSpan>.Value));
  • get instance property
    PropertyInfo property = typeof(DateTime).GetProperty("Second");
    PropertyInfo property = Metadata<DateTime>.Property(datetime => datetime.Second);

NOTE: instance resolution required a parameter expression to express an instance member and generic class Argument is a class helper to use as a token to discriminate the exact member.

Conclusion

Even if reflection is a cool thing, be careful when you use it. Fortunately, Puresharp Reflection API .NET 4.0+ provides a safer way to do it by only referencing a nuget package from nuget.org. This project is open source and under MIT licence, that allows you to use it without any restrictions.