Signum Framework Logo
"Open framework that encourages convention over configuration, using C# code,
not XML files, to model at the right level of abstraction and achieve deadlines.
...but also has a full Linq provider, and syncs the schema for you!"
Login
RSS

Search

»



Main
Index
Map
Videos
Download
Source code
Tutorials
Forum
FAQ



Image



PoweredBy

ReflectionTools class

ReflectionTools class contains some handy methods for some reflection scenarios, like strong typing reflection, or improving reflection performance through dynamic methods.

FieldEquals, PropertyEquals, MethodEquals and MemberEquals

Comparing if two System.Type objects are the same is as easy as using == operator. Unfortunately, that doesn't apply to any other object inheriting from MemberInfo (FieldInfo, PropertyInfo or MethodInfo). In order to compare them we use this methods:

public static bool FieldEquals(FieldInfo f1, FieldInfo f2)
public static bool PropertyEquals(PropertyInfo p1, PropertyInfo p2)
public static bool MethodEqual(MethodInfo m1, MethodInfo m2)
public static bool MemeberEquals(MemberInfo m1, MemberInfo m2)

Internally, they use the algorithm explained here.

Strong Typed Reflection

Reflection is all about adding dynamic features and introspection to .Net, but since System.Type has the cool typeof operator that allows strong-typed retrieval of System.Type objects, why should we rely on error-prone strings to retrieve other reflection entities, like FieldInfo, PropertyInfo, etc??

Strongly Typed Reflection uses Expression Trees to find the MemberInfo you are interested about. All you have to do is write a lambda witch root access (or invokes) the Field, Property or Method you are interested in.

This way you have IntelliSense and refactoring over your Reflection constants.

In the New version, some overloading have changed getting rid of object in favor of another generic parameter for performance reasons (now is extensively used in every entity property). In order to use the overloads that have two generic parameters is convenient to specify the argument in the parameter definition and let the compiler infer the return type.

public static PropertyInfo GetPropertyInfo<R>(Expression<Func<R>> property)
public static PropertyInfo GetPropertyInfo<T, R>(Expression<Func<T, R>> property)
public static PropertyInfo BasePropertyInfo(LambdaExpression property)

public static FieldInfo GetFieldInfo<R>(Expression<Func<R>> field) public static FieldInfo GetFieldInfo<T,R>(Expression<Func<T, R>> field) public static FieldInfo BaseFieldInfo(LambdaExpression field)

public static MemberInfo GetMemberInfo<R>(Expression<Func<R>> member) public static MemberInfo GetMemberInfo<T, R>(Expression<Func<T, R>> member) public static MemberInfo BaseMemberInfo(LambdaExpression member)

public static MethodInfo GetMethodInfo(Expression<Action> method) public static MethodInfo GetMethodInfo<R>(Expression<Func<R>> method) public static MethodInfo GetMethodInfo<T, R>(Expression<Func<T, R>> method) public static MethodInfo BaseMethodInfo(LambdaExpression method)

Example:

//Retrieving an static (readonly) field from string class
FieldInfo fi = ReflectionTools.GetFieldInfo(() => String.Empty);

//Retrieving an instance property info PropertyInfo pi = ReflectionTools.GetPropertyInfo((string s) => s.Length);

//Choosing between different overloads of the static methods Abs MethodInfo mi1 = ReflectionTools.GetMethodInfo((decimal d) => Math.Abs(d)); MethodInfo mi2 = ReflectionTools.GetMethodInfo((double d) => Math.Abs(d));

As you see, as long as the end (the root) of the expression tree you have the right field, property, or method, it will work fine.

DynamicMethod builders

Reflection is great. It makes huge code reductions. But it's famous for being slow, and this fame is well deserved. According to this article, this is the performance of different ways to call a method:

Image

Presumably, the same could be said for Fields and Properties.

DynamicMethods, however, let you compile a small function dynamically generated, returning a delegate. This way you can cache the delegate somewhere and not pay the performance penalty when doing this operation, like assigning a particular field in a particular type of objects, or calling a particular method.

ReflectionTools have some methods to build instance property and fields getters and setters, and constructors:

//Build a DynamicMethod like: (T obj)=>obj.m
public static Func<T, object> CreateGetter<T>(MemberInfo m)
//Builds a DynamicMethod like: (object obj)=>(('type')obj).m 
public static Func<object, object> CreateGetterUntyped(Type type, MemberInfo m)

//Build a DynamicMethod like: (T obj, object value)=>obj.m = value public static Action<T, object> CreateSetter<T>(MemberInfo m) //Build a DynamicMethod like: (object obj, object value)=>(('type')obj).m = value public static Action<object, object> CreateSetterUntyped(Type type, MemberInfo m)

//Build a DynamicMethod like: ()=>new T() public static Func<T> CreateConstructor<T>(Type type) //Build a DynamicMethod like: ()=>(object)new 'type'() public static Func<object> CreateConstructorUntyped(Type type)

Example:

//retrieving PropertyInfo with strong typed reflection 
//¬PropertyInfo piLength = ¬ReflectionTools.GetPropertyInfo((string s) => s.Length);
//retrieving PropertyInfo old-style
PropertyInfo piLength = typeof(string).GetProperty("Length");

//Compiling a delegate to get the property. Paying performance penalty once. Func<string, object> getLenght = ReflectionTools.CreateGetter<string>(piLength);

string[] cultureNames = CultureInfo.GetCultures(CultureTypes.NeutralCultures).Select(c => c.EnglishName).ToArray();

foreach (var name in cultureNames) { //using the getter many times with no overhead Console.WriteLine("{0} -> {1}", getLenght(name), name); } //Writes: //6 -> Arabic //9 -> Bulgarian //7 -> Catalan //20 -> Chinese (Simplified) //5 -> Czech //6 -> Danish //6 -> German //5 -> Greek //7 -> English //7 -> Spanish //7 -> Finnish //6 -> French //6 -> Hebrew //9 -> Hungarian //9 -> Icelandic //7 -> Italian //8 -> Japanese //6 -> Korean //5 -> Dutch //9 -> Norwegian //6 -> Polish //10 -> Portuguese //...

Parse Image

Tries to Parse the string in an object of the given type. Works with Enums and Nullables.

public static T Parse<T>(string value)
public static object Parse(string value, Type type)

Example:

ReflectionTools.Parse<double>("1.0"); //returns 1.0
ReflectionTools.Parse("1.0", typeof(double)); //return 1.0 boxed

ChangeType Image

Tries to convert an object to another type. Works with Enums and Nullables.

public static T ChangeType<T>(object value)
public static object ChangeType(object value, Type type)

Example:

ReflectionTools.Convert<DayOfWeek>(0); //returns Sunday
ReflectionTools.Convert(0, typeof(DayOfWeek)); //return Sunday 

CollectionType Image

If the type implements IEnumerable<T>, returns T, otherwise returns null.

public static Type CollectionType(Type ft)

Example:

ReflectionTools.CollectionType(typeof(List<int>)); //returns typeof(int)

Creative Commons License Signum Framework Site by Signum Software is licensed under a Creative Commons Attribution 3.0 License.
Powered by ScrewTurn Wiki version 3.0.5.600.