mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-15 15:09:29 +00:00
Removed boxing in TweenMemberss getters and setters (#1002)
* Removed boxing in TweenMemberss getters and setters * Removed unnecessary inclusions and comments * Simplified the get method creation on @AristurtleDev 's suggestion
This commit is contained in:
@@ -2,43 +2,45 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualBasic;
|
||||
|
||||
namespace MonoGame.Extended.Tweening
|
||||
{
|
||||
public sealed class TweenFieldMember<T> : TweenMember<T>
|
||||
where T : struct
|
||||
where T : struct
|
||||
{
|
||||
private readonly FieldInfo _fieldInfo;
|
||||
|
||||
public TweenFieldMember(object target, FieldInfo fieldInfo)
|
||||
public TweenFieldMember(object target, FieldInfo fieldInfo)
|
||||
: base(target, CompileGetMethod(fieldInfo), CompileSetMethod(fieldInfo))
|
||||
{
|
||||
_fieldInfo = fieldInfo;
|
||||
}
|
||||
|
||||
private static Func<object, object> CompileGetMethod(FieldInfo fieldInfo)
|
||||
private static Func<object, T> CompileGetMethod(FieldInfo fieldInfo)
|
||||
{
|
||||
var self = Expression.Parameter(typeof(object));
|
||||
var instance = Expression.Convert(self, fieldInfo.DeclaringType);
|
||||
var field = Expression.Field(instance, fieldInfo);
|
||||
var convert = Expression.TypeAs(field, typeof(object));
|
||||
|
||||
return Expression.Lambda<Func<object, object>>(convert, self).Compile();
|
||||
var entityType = fieldInfo.DeclaringType!;
|
||||
var parameter = Expression.Parameter(typeof(object), "entity");
|
||||
var property = Expression.Field(Expression.Convert(parameter, entityType), fieldInfo);
|
||||
return Expression.Lambda<Func<object, T>>(property, parameter).Compile();
|
||||
}
|
||||
|
||||
private static Action<object, object> CompileSetMethod(FieldInfo fieldInfo)
|
||||
private static Action<object, T> CompileSetMethod(FieldInfo fieldInfo)
|
||||
{
|
||||
Debug.Assert(fieldInfo.DeclaringType != null);
|
||||
|
||||
var self = Expression.Parameter(typeof(object));
|
||||
var value = Expression.Parameter(typeof(object));
|
||||
var fieldExp = Expression.Field(Expression.Convert(self, fieldInfo.DeclaringType), fieldInfo);
|
||||
var assignExp = Expression.Assign(fieldExp, Expression.Convert(value, fieldInfo.FieldType));
|
||||
var entityType = fieldInfo.DeclaringType!;
|
||||
var targetParam = Expression.Parameter(typeof(object), "target");
|
||||
var valueParam = Expression.Parameter(typeof(T), "value");
|
||||
var conversion = Expression.Convert(targetParam, entityType);
|
||||
|
||||
return Expression.Lambda<Action<object, object>>(assignExp, self, value).Compile();
|
||||
var field = Expression.Field(conversion, fieldInfo);
|
||||
var assignation = Expression.Assign(field, valueParam);
|
||||
|
||||
return Expression.Lambda<Action<object, T>>(assignation, targetParam, valueParam).Compile();
|
||||
}
|
||||
|
||||
public override Type Type => _fieldInfo.FieldType;
|
||||
public override string Name => _fieldInfo.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,19 @@ namespace MonoGame.Extended.Tweening
|
||||
public abstract class TweenMember<T> : TweenMember
|
||||
where T : struct
|
||||
{
|
||||
protected TweenMember(object target, Func<object, object> getMethod, Action<object, object> setMethod)
|
||||
protected TweenMember(object target, Func<object, T> getMethod, Action<object, T> setMethod)
|
||||
: base(target)
|
||||
{
|
||||
_getMethod = getMethod;
|
||||
_setMethod = setMethod;
|
||||
}
|
||||
|
||||
private readonly Func<object, object> _getMethod;
|
||||
private readonly Action<object, object> _setMethod;
|
||||
private readonly Func<object, T> _getMethod;
|
||||
private readonly Action<object, T> _setMethod;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get { return (T) _getMethod(Target); }
|
||||
get { return _getMethod(Target); }
|
||||
set { _setMethod(Target, value); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Reflection;
|
||||
namespace MonoGame.Extended.Tweening
|
||||
{
|
||||
public sealed class TweenPropertyMember<T> : TweenMember<T>
|
||||
where T : struct
|
||||
where T : struct
|
||||
{
|
||||
private readonly PropertyInfo _propertyInfo;
|
||||
|
||||
@@ -19,25 +19,29 @@ namespace MonoGame.Extended.Tweening
|
||||
public override Type Type => _propertyInfo.PropertyType;
|
||||
public override string Name => _propertyInfo.Name;
|
||||
|
||||
private static Func<object, object> CompileGetMethod(PropertyInfo propertyInfo)
|
||||
//TODO: Try to further optimize this. For example, it needs to do all this reflection compilation shenanigan every time.
|
||||
//Could we cache these instead?
|
||||
|
||||
private static Func<object, T> CompileGetMethod(PropertyInfo propertyInfo)
|
||||
{
|
||||
var param = Expression.Parameter(typeof(object));
|
||||
var instance = Expression.Convert(param, propertyInfo.DeclaringType);
|
||||
var convert = Expression.TypeAs(Expression.Property(instance, propertyInfo), typeof(object));
|
||||
return Expression.Lambda<Func<object, object>>(convert, param).Compile();
|
||||
var entityType = propertyInfo.DeclaringType!;
|
||||
var parameter = Expression.Parameter(typeof(object), "entity");
|
||||
var property = Expression.Property(Expression.Convert(parameter, entityType), propertyInfo);
|
||||
return Expression.Lambda<Func<object, T>>(property, parameter).Compile();
|
||||
}
|
||||
|
||||
private static Action<object, object> CompileSetMethod(PropertyInfo propertyInfo)
|
||||
private static Action<object, T> CompileSetMethod(PropertyInfo propertyInfo)
|
||||
{
|
||||
Debug.Assert(propertyInfo.DeclaringType != null);
|
||||
|
||||
var param = Expression.Parameter(typeof(object));
|
||||
var argument = Expression.Parameter(typeof(object));
|
||||
var expression = Expression.Convert(param, propertyInfo.DeclaringType);
|
||||
var methodInfo = propertyInfo.SetMethod;
|
||||
var arguments = Expression.Convert(argument, propertyInfo.PropertyType);
|
||||
var setterCall = Expression.Call(expression, methodInfo, arguments);
|
||||
return Expression.Lambda<Action<object, object>>(setterCall, param, argument).Compile();
|
||||
var entityType = propertyInfo.DeclaringType!;
|
||||
var targetParam = Expression.Parameter(typeof(object), "target");
|
||||
var valueParam = Expression.Parameter(typeof(T), "value");
|
||||
var conversion = Expression.Convert(targetParam, entityType);
|
||||
var methodInfo = propertyInfo.SetMethod!;
|
||||
var set = Expression.Call(conversion, methodInfo, valueParam);
|
||||
|
||||
return Expression.Lambda<Action<object, T>>(set, targetParam, valueParam).Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user