Skip to content

Commit

Permalink
Minor cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
lanwin committed May 25, 2010
1 parent 2aba834 commit 5e288db
Showing 1 changed file with 65 additions and 67 deletions.
Expand Up @@ -3,137 +3,135 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

using MongoDB.Util;

namespace MongoDB.Configuration.Mapping.Model
{
/// <summary>
///
/// </summary>
public static class MemberReflectionOptimizer
{
private static readonly Dictionary<string, Func<object, object>> getterCache = new Dictionary<string, Func<object, object>>();
private static readonly Dictionary<string, Action<object, object>> setterCache = new Dictionary<string, Action<object, object>>();
private static readonly Dictionary<string, Func<object, object>> GetterCache = new Dictionary<string, Func<object, object>>();
private static readonly Dictionary<string, Action<object, object>> SetterCache = new Dictionary<string, Action<object, object>>();

/// <summary>
/// Gets the getter.
/// Gets the getter.
/// </summary>
/// <param name="memberInfo">The member info.</param>
/// <param name = "memberInfo">The member info.</param>
/// <returns></returns>
public static Func<object, object> GetGetter(MemberInfo memberInfo)
{
if (memberInfo == null)
if(memberInfo == null)
throw new ArgumentNullException("memberInfo");
if (memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property)
if(memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property)
throw new ArgumentException("Only fields and properties are supported.", "memberInfo");

if (memberInfo.MemberType == MemberTypes.Field)
if(memberInfo.MemberType == MemberTypes.Field)
return GetFieldGetter(memberInfo as FieldInfo);
if (memberInfo.MemberType == MemberTypes.Property)

if(memberInfo.MemberType == MemberTypes.Property)
return GetPropertyGetter(memberInfo as PropertyInfo);

throw new InvalidOperationException("Can only create getters for fields or properties.");
}

/// <summary>
/// Gets the field getter.
/// Gets the field getter.
/// </summary>
/// <param name="fieldInfo">The field info.</param>
/// <param name = "fieldInfo">The field info.</param>
/// <returns></returns>
public static Func<object, object> GetFieldGetter(FieldInfo fieldInfo)
{
if (fieldInfo == null)
if(fieldInfo == null)
throw new ArgumentNullException("fieldInfo");

var key = CreateKey(fieldInfo);
if (getterCache.ContainsKey(key))
return getterCache[key];
if(GetterCache.ContainsKey(key))
return GetterCache[key];

ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target");
var instanceParameter = Expression.Parameter(typeof(object), "target");

MemberExpression member = Expression.Field(Expression.Convert(instanceParameter, fieldInfo.DeclaringType), fieldInfo);
var member = Expression.Field(Expression.Convert(instanceParameter, fieldInfo.DeclaringType), fieldInfo);

Expression<Func<object, object>> lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(member, typeof(object)),
instanceParameter);
var lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(member, typeof(object)),
instanceParameter);

var result = lambda.Compile();
getterCache[key] = result;
GetterCache[key] = result;
return result;
}

/// <summary>
/// Gets the property getter.
/// Gets the property getter.
/// </summary>
/// <param name="propertyInfo">The property info.</param>
/// <param name = "propertyInfo">The property info.</param>
/// <returns></returns>
public static Func<object, object> GetPropertyGetter(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
if(propertyInfo == null)
throw new ArgumentNullException("propertyInfo");

var key = CreateKey(propertyInfo);
if (getterCache.ContainsKey(key))
return getterCache[key];
if(GetterCache.ContainsKey(key))
return GetterCache[key];

if (!propertyInfo.CanRead)
if(!propertyInfo.CanRead)
throw new InvalidOperationException("Cannot create a getter for a writeonly property.");

ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target");
var instanceParameter = Expression.Parameter(typeof(object), "target");

MemberExpression member = Expression.Property(Expression.Convert(instanceParameter, propertyInfo.DeclaringType), propertyInfo);
var member = Expression.Property(Expression.Convert(instanceParameter, propertyInfo.DeclaringType), propertyInfo);

Expression<Func<object, object>> lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(member, typeof(object)),
instanceParameter);
var lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(member, typeof(object)),
instanceParameter);

var result = lambda.Compile();
getterCache[key] = result;
GetterCache[key] = result;
return result;
}

/// <summary>
/// Gets the setter.
/// Gets the setter.
/// </summary>
/// <param name="memberInfo">The member info.</param>
/// <param name = "memberInfo">The member info.</param>
/// <returns></returns>
public static Action<object, object> GetSetter(MemberInfo memberInfo)
{
if (memberInfo == null)
if(memberInfo == null)
throw new ArgumentNullException("memberInfo");
if (memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property)
if(memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property)
throw new ArgumentException("Only fields and properties are supported.", "memberInfo");

if (memberInfo.MemberType == MemberTypes.Field)
if(memberInfo.MemberType == MemberTypes.Field)
return GetFieldSetter(memberInfo as FieldInfo);
if (memberInfo.MemberType == MemberTypes.Property)

if(memberInfo.MemberType == MemberTypes.Property)
return GetPropertySetter(memberInfo as PropertyInfo);

throw new InvalidOperationException("Can only create setters for fields or properties.");
}

/// <summary>
/// Gets the field setter.
/// Gets the field setter.
/// </summary>
/// <param name="fieldInfo">The field info.</param>
/// <param name = "fieldInfo">The field info.</param>
/// <returns></returns>
public static Action<object, object> GetFieldSetter(FieldInfo fieldInfo)
{
if (fieldInfo == null)
if(fieldInfo == null)
throw new ArgumentNullException("fieldInfo");

var key = CreateKey(fieldInfo);
if (setterCache.ContainsKey(key))
return setterCache[key];
if(SetterCache.ContainsKey(key))
return SetterCache[key];

if (fieldInfo.IsInitOnly || fieldInfo.IsLiteral)
if(fieldInfo.IsInitOnly || fieldInfo.IsLiteral)
throw new InvalidOperationException("Cannot create a setter for a readonly field.");

var sourceType = fieldInfo.DeclaringType;
var method = new DynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(object), typeof(object) }, true);
var method = new DynamicMethod("Set" + fieldInfo.Name, null, new[] {typeof(object), typeof(object)}, true);
var gen = method.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
Expand All @@ -144,47 +142,47 @@ public static class MemberReflectionOptimizer
gen.Emit(OpCodes.Ret);

var result = (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
setterCache[key] = result;
SetterCache[key] = result;
return result;
}

/// <summary>
/// Gets the property setter.
/// Gets the property setter.
/// </summary>
/// <param name="propertyInfo">The property info.</param>
/// <param name = "propertyInfo">The property info.</param>
/// <returns></returns>
public static Action<object, object> GetPropertySetter(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
if(propertyInfo == null)
throw new ArgumentNullException("propertyInfo");

var key = CreateKey(propertyInfo);
if (setterCache.ContainsKey(key))
return setterCache[key];
if(SetterCache.ContainsKey(key))
return SetterCache[key];

if (!propertyInfo.CanWrite)
if(!propertyInfo.CanWrite)
throw new InvalidOperationException("Cannot create a setter for a readonly property.");

ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "target");
ParameterExpression valueParameter = Expression.Parameter(typeof(object), "value");
var instanceParameter = Expression.Parameter(typeof(object), "target");
var valueParameter = Expression.Parameter(typeof(object), "value");

Expression<Action<object, object>> lambda = Expression.Lambda<Action<object, object>>(
Expression.Call(
Expression.Convert(instanceParameter, propertyInfo.DeclaringType),
propertyInfo.GetSetMethod(true),
Expression.Convert(valueParameter, propertyInfo.PropertyType)),
instanceParameter,
valueParameter);
var lambda = Expression.Lambda<Action<object, object>>(
Expression.Call(
Expression.Convert(instanceParameter, propertyInfo.DeclaringType),
propertyInfo.GetSetMethod(true),
Expression.Convert(valueParameter, propertyInfo.PropertyType)),
instanceParameter,
valueParameter);

var result = lambda.Compile();
setterCache[key] = result;
SetterCache[key] = result;
return result;
}

/// <summary>
/// Creates the key.
/// Creates the key.
/// </summary>
/// <param name="memberInfo">The member info.</param>
/// <param name = "memberInfo">The member info.</param>
/// <returns></returns>
private static string CreateKey(MemberInfo memberInfo)
{
Expand Down

0 comments on commit 5e288db

Please sign in to comment.