Fix GetterSetter

Fix builing fast getter setter for type fields and properties.
Implemented a more correct conversion.
pull/1/head
Ogoun 6 years ago
parent b6a836f3b6
commit 1a7ccf9ded

@ -55,7 +55,7 @@ namespace ZeroLevel.Services.ObjectMapping
private static MapMemberInfo FromField(FieldInfo fieldInfo)
{
var field = new MapMemberInfo(fieldInfo.BuildSetter(), fieldInfo.BuildGetter())
var field = new MapMemberInfo(TypeGetterSetterBuilder.BuildSetter(fieldInfo), TypeGetterSetterBuilder.BuildGetter(fieldInfo))
{
Name = fieldInfo.Name
};
@ -67,7 +67,7 @@ namespace ZeroLevel.Services.ObjectMapping
private static IMemberInfo FromProperty(PropertyInfo propertyInfo)
{
var field = new MapMemberInfo(propertyInfo.BuildSetter(), propertyInfo.BuildGetter())
var field = new MapMemberInfo(TypeGetterSetterBuilder.BuildSetter(propertyInfo), TypeGetterSetterBuilder.BuildGetter(propertyInfo))
{
Name = propertyInfo.Name
};

@ -1,16 +0,0 @@
using System;
using System.Reflection;
namespace ZeroLevel.Services.Reflection
{
public interface ITypeFastAccessMethodBuilder
{
Func<object, object> BuildGetter(PropertyInfo property);
Func<object, object> BuildGetter(FieldInfo field);
Action<object, object> BuildSetter(PropertyInfo property);
Action<object, object> BuildSetter(FieldInfo field);
}
}

@ -1,35 +0,0 @@
using System;
using System.Reflection;
namespace ZeroLevel.Services.Reflection
{
public static class TypeFastAccessMethodBuilder
{
private readonly static ITypeFastAccessMethodBuilder _builder;
static TypeFastAccessMethodBuilder()
{
_builder = new TypeFastAccessMethodBuilderImpl();
}
public static Func<object, object> BuildGetter(this FieldInfo field)
{
return _builder.BuildGetter(field);
}
public static Func<object, object> BuildGetter(this PropertyInfo property)
{
return _builder.BuildGetter(property);
}
public static Action<object, object> BuildSetter(this FieldInfo field)
{
return _builder.BuildSetter(field);
}
public static Action<object, object> BuildSetter(this PropertyInfo property)
{
return _builder.BuildSetter(property);
}
}
}

@ -1,79 +0,0 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ZeroLevel.Services.Reflection
{
public class TypeFastAccessMethodBuilderImpl : ITypeFastAccessMethodBuilder
{
public Func<object, object> BuildGetter(PropertyInfo property)
{
if (property == null) return null;
if (property.CanRead == false) return null;
var getterMethodInfo = property.GetGetMethod();
var entity = Expression.Parameter(typeof(object), "o");
var target = property.DeclaringType.IsValueType ?
Expression.Unbox(entity, property.DeclaringType) :
Expression.Convert(entity, property.DeclaringType);
var getterCall = Expression.Call(target, getterMethodInfo);
var castToObject = Expression.Convert(getterCall, typeof(object));
var lambda = Expression.Lambda(castToObject, entity);
return (Func<object, object>)lambda.Compile();
}
public Func<object, object> BuildGetter(FieldInfo field)
{
if (field == null) return null;
var entity = Expression.Parameter(typeof(object), "o");
var target = field.DeclaringType.IsValueType ?
Expression.Unbox(entity, field.DeclaringType) :
Expression.Convert(entity, field.DeclaringType);
var fieldExp = Expression.Field(target, field);
var castToObject = Expression.Convert(fieldExp, typeof(object));
var lambda = Expression.Lambda(castToObject, entity);
return (Func<object, object>)lambda.Compile();
}
/// <summary>
/// Creates a quick setter for a property
/// </summary>
public Action<object, object> BuildSetter(PropertyInfo property)
{
if (property == null) return null;
if (property.CanWrite == false) return null;
var method = property.GetSetMethod(true);
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
var target = property.DeclaringType.IsValueType ?
Expression.Unbox(obj, method.DeclaringType) :
Expression.Convert(obj, method.DeclaringType);
var expr = Expression.
Lambda<Action<object, object>>(Expression.Call(target, method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj, value);
return expr.Compile();
}
/// <summary>
/// Creates a quick setter for a field.
/// </summary>
public Action<object, object> BuildSetter(FieldInfo field)
{
if (field == null) return null;
var targetExp = Expression.Parameter(field.DeclaringType, "target");
var valueExp = Expression.Parameter(typeof(object), "value");
// Expression.Property can be used here as well
var obj = Expression.Parameter(typeof(object), "o");
var target = field.DeclaringType.IsValueType ?
Expression.Unbox(obj, field.DeclaringType) :
Expression.Convert(obj, field.DeclaringType);
var fieldExp = Expression.Field(target, field);
var assignExp = Expression.Assign(fieldExp, Expression.Convert(valueExp, field.FieldType));
return Expression.Lambda<Action<object, object>>
(assignExp, obj, valueExp).Compile();
}
}
}

@ -0,0 +1,129 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ZeroLevel.Services.Reflection
{
public static class TypeGetterSetterBuilder
{
public static Func<object, object> BuildGetter(FieldInfo field)
{
if (field == null) return null;
var entity = Expression.Parameter(typeof(object), "o");
var target = field.DeclaringType.IsValueType ?
Expression.Unbox(entity, field.DeclaringType) :
Expression.Convert(entity, field.DeclaringType);
var fieldExp = Expression.Field(target, field);
var castToObject = Expression.Convert(fieldExp, typeof(object));
var lambda = Expression.Lambda(castToObject, entity);
return (Func<object, object>)lambda.Compile();
}
public static Func<object, object> BuildGetter(PropertyInfo property)
{
if (property == null) return null;
if (property.CanRead == false) return null;
var getterMethodInfo = property.GetGetMethod();
var entity = Expression.Parameter(typeof(object), "o");
var target = property.DeclaringType.IsValueType ?
Expression.Unbox(entity, property.DeclaringType) :
Expression.Convert(entity, property.DeclaringType);
var getterCall = Expression.Call(target, getterMethodInfo);
var castToObject = Expression.Convert(getterCall, typeof(object));
var lambda = Expression.Lambda(castToObject, entity);
return (Func<object, object>)lambda.Compile();
}
/// <summary>
/// Creates a quick setter for a field.
/// </summary>
public static Action<object, object> BuildSetter(FieldInfo field)
{
if (field == null)
{
return null;
}
var instance = Expression.Parameter(typeof(object), "target");
var inputValue = Expression.Parameter(typeof(object), "value");
var target = field.DeclaringType.IsValueType ?
Expression.Unbox(instance, field.DeclaringType) :
Expression.Convert(instance, field.DeclaringType);
var fieldExp = Expression.Field(target, field);
var typeCode = Type.GetTypeCode(field.FieldType);
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var convertExpression = Expression.Call(changeTypeMethod, inputValue, Expression.Constant(typeCode));
var assignExp = Expression.Assign(fieldExp, field.FieldType.IsValueType ?
Expression.Convert(convertExpression, field.FieldType) :
Expression.TypeAs(convertExpression, field.FieldType));
return Expression.Lambda<Action<object, object>>(assignExp, instance, inputValue).Compile();
}
/// <summary>
/// Creates a quick setter for a property
/// </summary>
public static Action<object, object> BuildSetter(PropertyInfo property)
{
if (property == null || property.CanWrite == false)
{
return null;
}
var instance = Expression.Parameter(typeof(object), "target");
var inputValue = Expression.Parameter(typeof(object), "value");
var target = property.DeclaringType.IsValueType ?
Expression.Unbox(instance, property.DeclaringType) :
Expression.Convert(instance, property.DeclaringType);
var method = property.GetSetMethod(true);
var typeCode = Type.GetTypeCode(property.PropertyType);
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var convertExpression = Expression.Call(changeTypeMethod, inputValue, Expression.Constant(typeCode));
var setterCall = Expression.Call(target, method, Expression.Convert(convertExpression, property.PropertyType));
var expr = Expression.Lambda<Action<object, object>>(setterCall, instance, inputValue);
return expr.Compile();
}
/// <summary>
/// Creates a quick setter for a field.
/// </summary>
public static Action<T, object> BuildSetter<T>(FieldInfo field)
{
if (field == null || typeof(T) != field.DeclaringType)
{
return null;
}
var targetExp = Expression.Parameter(typeof(T), "target");
var inputValue = Expression.Parameter(typeof(object), "o");
var fieldExp = Expression.Field(targetExp, field);
var typeCode = Type.GetTypeCode(field.FieldType);
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var convertExpression = Expression.Call(changeTypeMethod, inputValue, Expression.Constant(typeCode));
var assignExp = Expression.Assign(fieldExp, Expression.Convert(convertExpression, field.FieldType));
return Expression.Lambda<Action<T, object>>(assignExp, targetExp, inputValue).Compile();
}
/// <summary>
/// Creates a quick setter for a property
/// </summary>
public static Action<T, object> BuildSetter<T>(PropertyInfo property)
{
if (property == null || typeof(T) != property.DeclaringType || property.CanWrite == false)
{
return null;
}
var method = property.GetSetMethod(true);
var instance = Expression.Parameter(property.DeclaringType, "i");
var target = property.DeclaringType.IsValueType ?
Expression.Unbox(instance, method.DeclaringType) :
Expression.Convert(instance, method.DeclaringType);
var value = Expression.Parameter(typeof(object), "v");
var typeCode = Type.GetTypeCode(property.PropertyType);
var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(TypeCode) });
var convertExpression = Expression.Call(changeTypeMethod, value, Expression.Constant(typeCode));
var setterCall = Expression.Call(target, method, Expression.Convert(convertExpression, property.PropertyType));
var expr = Expression.Lambda<Action<T, object>>(setterCall, instance, value);
return expr.Compile();
}
}
}

@ -254,7 +254,7 @@ namespace ZeroLevel.Services.Serialization
{
instance.Deserialize(reader);
}
return TypeFastAccessMethodBuilder.BuildGetter(rt.GetProperty("Value"))(instance);
return TypeGetterSetterBuilder.BuildGetter(rt.GetProperty("Value"))(instance);
}
}
}

@ -279,12 +279,10 @@
<Compile Include="Services\Queries\Storage\IStorage.cs" />
<Compile Include="Services\Queries\Storage\MemoryStorage.cs" />
<Compile Include="Services\Queries\Storage\QueryResult.cs" />
<Compile Include="Services\Reflection\ITypeFastAccessMethodBuilder.cs" />
<Compile Include="Services\Reflection\ReferenceHelper.cs" />
<Compile Include="Services\Reflection\StringToTypeConverter.cs" />
<Compile Include="Services\Reflection\TypeActivator.cs" />
<Compile Include="Services\Reflection\TypeFastAccessMethodBuilder.cs" />
<Compile Include="Services\Reflection\TypeFastAccessMethodBuilderImpl.cs" />
<Compile Include="Services\Reflection\TypeGetterSetterBuilder.cs" />
<Compile Include="Services\Reflection\TypeHelpers.cs" />
<Compile Include="Services\Semantic\Contracts\ILexer.cs" />
<Compile Include="Services\Semantic\Contracts\ILexProvider.cs" />

Loading…
Cancel
Save

Powered by TurnKey Linux.