Skip to content

Instantly share code, notes, and snippets.

@jwatney
Created April 8, 2012 18:54
Show Gist options
  • Save jwatney/2339182 to your computer and use it in GitHub Desktop.
Save jwatney/2339182 to your computer and use it in GitHub Desktop.
Fast Property Info-type class.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace TypeUtil {
public static class TypeExtensions {
public static FastPropertyInfo<T> GetProperty<T>(this Type type, string name) {
return type.GetProperty<T>(name, BindingFlags.Default);
}
public static FastPropertyInfo<T> GetProperty<T>(this Type type, string name, BindingFlags flags) {
var property = type.GetProperty(name, flags);
if(property == null) {
return null;
}
return new FastPropertyInfo<T>(property);
}
}
public class FastPropertyInfo<T> {
private PropertyInfo info;
private Func<T, object[], object> getter;
private Action<T, object, object[]> setter;
public bool CanRead { get { return info.CanRead; } }
public bool CanWrite { get { return info.CanWrite; } }
public FastPropertyInfo(PropertyInfo info) {
this.info = info;
getter = CreateGetValue(info);
setter = CreateSetValue(info);
}
public object GetValue(T instance, object[] index) {
if(getter == null) {
throw new ArgumentException("The property's get accessor is not found.");
}
return getter(instance, index);
}
public void SetValue(T instance, object value, object[] index) {
if(setter == null) {
throw new ArgumentException("The property's set accessor is not found.");
}
setter(instance, value, index);
}
private static Func<T, object[], object> CreateGetValue(PropertyInfo info) {
if(!info.CanRead) {
return null;
}
// info.GetValue(instance, null);
var instanceExpression = Expression.Parameter(typeof(T), "instance");
var indexExpression = Expression.Parameter(typeof(object[]), "index");
var getExpression = Expression.Call(instanceExpression, info.GetGetMethod());
var lambdaExpression = Expression.Lambda<Func<T, object[], object>>(Expression.Convert(getExpression, typeof(object)), instanceExpression, indexExpression);
return lambdaExpression.Compile();
}
private static Action<T, object, object[]> CreateSetValue(PropertyInfo info) {
if(!info.CanWrite) {
return null;
}
// info.SetValue(instance, value, null);
var valueType = info.GetSetMethod().GetParameters()[0].ParameterType;
var instanceExpression = Expression.Parameter(typeof(T), "instance");
var valueExpression = Expression.Parameter(valueType, "value");
var indexExpression = Expression.Parameter(typeof(object[]), "index");
var setExpression = Expression.Call(instanceExpression, info.GetSetMethod(), valueExpression, indexExpression);
var lambdaExpression = Expression.Lambda<Action<T, object, object[]>>(setExpression, instanceExpression, valueExpression, indexExpression);
return lambdaExpression.Compile();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment