Created
July 6, 2012 10:33
-
-
Save Allon-Guralnek/3059427 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics.Contracts; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
public class DynamicPropertyAccessor<TObject, TProperty> | |
{ | |
public string Name { get; private set; } | |
public Type PropertyType { get; private set; } | |
private Lazy<Func<TObject, TProperty>> Getter { get; set; } | |
private Lazy<Action<TObject, TProperty>> Setter { get; set; } | |
public DynamicPropertyAccessor(PropertyInfo targetProperty) | |
{ | |
Contract.Requires<ArgumentNullException>(targetProperty != null); | |
Name = targetProperty.Name; | |
PropertyType = targetProperty.PropertyType; | |
var objectParam = Expression.Parameter(typeof(TObject), "object"); | |
var specificObject = Expression.Convert(objectParam, targetProperty.ReflectedType); | |
var property = Expression.Property(specificObject, targetProperty); | |
if (targetProperty.CanRead) | |
{ | |
// Getter | |
var convertToObject = Expression.Convert(property, typeof(TProperty)); | |
var getter = Expression.Lambda<Func<TObject, TProperty>>(convertToObject, objectParam); | |
Getter = new Lazy<Func<TObject, TProperty>>(getter.Compile); | |
} | |
if (targetProperty.CanWrite) | |
{ | |
// Setter | |
var valueParam = Expression.Parameter(typeof(TProperty), "value"); | |
var value = Expression.Convert(valueParam, PropertyType); | |
var assign = Expression.Assign(property, value); | |
var setter = Expression.Lambda<Action<TObject, TProperty>>(assign, objectParam, valueParam); | |
Setter = new Lazy<Action<TObject, TProperty>>(setter.Compile); | |
} | |
} | |
public TProperty this[TObject obj] | |
{ | |
get | |
{ | |
Contract.Requires(obj != null); | |
if (Getter == null) | |
throw new InvalidOperationException(string.Format("The property '{0}', represented by this DynamicPropertyAccessor, is not readable.", Name)); | |
return Getter.Value(obj); | |
} | |
set | |
{ | |
Contract.Requires(obj != null); | |
if (Setter == null) | |
throw new InvalidOperationException(string.Format("The property '{0}', represented by this DynamicPropertyAccessor, is not writeable.", Name)); | |
Setter.Value(obj, value); | |
} | |
} | |
} | |
public class DynamicPropertyAccessor : DynamicPropertyAccessor<object, object> | |
{ | |
public DynamicPropertyAccessor(PropertyInfo targetProperty) : base(targetProperty) { } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment