[Core] Remove ILGen
This commit is contained in:
Родитель
bcbd312539
Коммит
12145ecc6b
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection.Emit;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.PropertyEditing
|
||||
|
@ -28,6 +28,17 @@ namespace Xamarin.PropertyEditing
|
|||
private static Func<T, T> IncrementValue, DecrementValue;
|
||||
private static NullableConverter NullConverter;
|
||||
|
||||
private static Func<T, T> GetNullableVersion (Expression shiftExpression, Type realType)
|
||||
{
|
||||
var v = Expression.Parameter (typeof(T));
|
||||
var convert = Expression.Call (Expression.Constant (NullConverter), nameof(NullableConverter.ConvertFrom), null, Expression.Convert (v, typeof(object)));
|
||||
var shift = Expression.Invoke (shiftExpression, Expression.Convert (convert, realType));
|
||||
var conditional = Expression.Condition (Expression.Equal (v, Expression.Constant (null)), Expression.Default (realType), shift);
|
||||
|
||||
// (T v) => (T)((v == null) ? default(realType) : shiftExpression ((realType)NullableConverter.ConvertFrom ((object)v));
|
||||
return Expression.Lambda<Func<T, T>> (Expression.Convert (conditional, typeof(T)), v).Compile();
|
||||
}
|
||||
|
||||
private static void SetupMath ()
|
||||
{
|
||||
if (IncrementValue != null)
|
||||
|
@ -40,110 +51,41 @@ namespace Xamarin.PropertyEditing
|
|||
t = Nullable.GetUnderlyingType (t);
|
||||
}
|
||||
|
||||
Task<Func<T, T>> createIncrement = Task.Run (() => {
|
||||
var add = new DynamicMethod ("Add", t, new[] { t });
|
||||
ILGenerator gen = add.GetILGenerator ();
|
||||
gen.Emit (OpCodes.Ldarg_0);
|
||||
Task<Func<T,T>> createIncrement = Task.Run (() => {
|
||||
var value = Expression.Parameter (t);
|
||||
|
||||
switch (Type.GetTypeCode (t)) {
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
gen.Emit (OpCodes.Ldc_I4_1);
|
||||
gen.Emit (OpCodes.Add_Ovf_Un);
|
||||
break;
|
||||
case TypeCode.UInt64:
|
||||
gen.Emit (OpCodes.Ldc_I8, 1L);
|
||||
gen.Emit (OpCodes.Add_Ovf_Un);
|
||||
break;
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
gen.Emit (OpCodes.Ldc_I4_1);
|
||||
gen.Emit (OpCodes.Add_Ovf);
|
||||
break;
|
||||
case TypeCode.Int64:
|
||||
gen.Emit (OpCodes.Ldc_I8, 1L);
|
||||
gen.Emit (OpCodes.Add_Ovf);
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
gen.Emit (OpCodes.Ldc_R4, 1f);
|
||||
gen.Emit (OpCodes.Add);
|
||||
break;
|
||||
case TypeCode.Double:
|
||||
gen.Emit (OpCodes.Ldc_R8, 1d);
|
||||
gen.Emit (OpCodes.Add);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
Expression add;
|
||||
if (t == typeof(byte) || t == typeof(sbyte)) {
|
||||
// (t value) => (t)((int)value + 1);
|
||||
add = Expression.Convert (Expression.Add (Expression.Convert (value, typeof(int)), Expression.Constant (1)), t);
|
||||
} else {
|
||||
var shiftby = Expression.Convert (Expression.Constant (1), t);
|
||||
add = Expression.Add (value, shiftby);
|
||||
}
|
||||
|
||||
gen.Emit (OpCodes.Ret);
|
||||
if (!isNullable)
|
||||
return (Func<T,T>)add.CreateDelegate (typeof(Func<T, T>));
|
||||
else {
|
||||
Delegate a = add.CreateDelegate (typeof(Func<,>).MakeGenericType (new[] { t, t }));
|
||||
return (v) => {
|
||||
if (v == null)
|
||||
return (T)Activator.CreateInstance (t);
|
||||
else {
|
||||
return (T)a.DynamicInvoke (NullConverter.ConvertFrom (v));
|
||||
}
|
||||
};
|
||||
}
|
||||
var increment = Expression.Lambda (add, value);
|
||||
if (isNullable)
|
||||
return GetNullableVersion (increment, t);
|
||||
|
||||
return (Func<T, T>)increment.Compile();
|
||||
});
|
||||
|
||||
Task<Func<T, T>> createDecrement = Task.Run (() => {
|
||||
var sub = new DynamicMethod ("Sub", t, new[] { t });
|
||||
ILGenerator gen = sub.GetILGenerator ();
|
||||
gen.Emit (OpCodes.Ldarg_0);
|
||||
Task<Func<T,T>> createDecrement = Task.Run (() => {
|
||||
var shiftby = Expression.Convert (Expression.Constant (1), t);
|
||||
var value = Expression.Parameter (t);
|
||||
|
||||
switch (Type.GetTypeCode (t)) {
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
gen.Emit (OpCodes.Ldc_I4_1);
|
||||
gen.Emit (OpCodes.Sub_Ovf_Un);
|
||||
break;
|
||||
case TypeCode.UInt64:
|
||||
gen.Emit (OpCodes.Ldc_I8, 1L);
|
||||
gen.Emit (OpCodes.Sub_Ovf_Un);
|
||||
break;
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
gen.Emit (OpCodes.Ldc_I4_1);
|
||||
gen.Emit (OpCodes.Sub_Ovf);
|
||||
break;
|
||||
case TypeCode.Int64:
|
||||
gen.Emit (OpCodes.Ldc_I8, 1L);
|
||||
gen.Emit (OpCodes.Sub_Ovf);
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
gen.Emit (OpCodes.Ldc_R4, 1f);
|
||||
gen.Emit (OpCodes.Sub);
|
||||
break;
|
||||
case TypeCode.Double:
|
||||
gen.Emit (OpCodes.Ldc_R8, 1d);
|
||||
gen.Emit (OpCodes.Sub);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
Expression sub;
|
||||
if (t == typeof(byte) || t == typeof(sbyte)) {
|
||||
sub = Expression.Convert (Expression.Subtract (Expression.Convert (value, typeof(int)), Expression.Constant (1)), t);
|
||||
} else {
|
||||
sub = Expression.Subtract (value, shiftby);
|
||||
}
|
||||
|
||||
gen.Emit (OpCodes.Ret);
|
||||
if (!isNullable)
|
||||
return (Func<T,T>)sub.CreateDelegate (typeof(Func<T, T>));
|
||||
else {
|
||||
Delegate s = sub.CreateDelegate (typeof(Func<,>).MakeGenericType (t, t));
|
||||
return (v) => {
|
||||
if (v == null)
|
||||
return (T)Activator.CreateInstance (t);
|
||||
else {
|
||||
return (T)s.DynamicInvoke (NullConverter.ConvertFrom (v));
|
||||
}
|
||||
};
|
||||
}
|
||||
var decrement = Expression.Lambda (sub, value);
|
||||
if (isNullable)
|
||||
return GetNullableVersion (decrement, t);
|
||||
|
||||
return (Func<T, T>)decrement.Compile();
|
||||
});
|
||||
|
||||
IncrementValue = createIncrement.Result;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.PropertyEditing.Reflection
|
||||
|
@ -131,12 +131,8 @@ namespace Xamarin.PropertyEditing.Reflection
|
|||
{
|
||||
return Casters.GetOrAdd (typeof(T), t => {
|
||||
return Task.Run (() => {
|
||||
DynamicMethod method = new DynamicMethod ("Caster", typeof(T), new[] { typeof(object) });
|
||||
ILGenerator generator = method.GetILGenerator ();
|
||||
generator.Emit (OpCodes.Ldarg_0);
|
||||
generator.Emit (OpCodes.Castclass, typeof(T));
|
||||
generator.Emit (OpCodes.Ret);
|
||||
return method.CreateDelegate (typeof(Func<object, T>));
|
||||
var arg = Expression.Parameter (typeof(object));
|
||||
return Expression.Lambda (Expression.Convert (arg, typeof(T)), arg).Compile ();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -145,24 +141,10 @@ namespace Xamarin.PropertyEditing.Reflection
|
|||
{
|
||||
return HasFlagsMethods.GetOrAdd (typeof(T), t => {
|
||||
return Task.Run (() => {
|
||||
DynamicMethod method = new DynamicMethod ("HasFlags", typeof(bool), new[] { typeof(T), typeof(T) });
|
||||
ILGenerator generator = method.GetILGenerator ();
|
||||
generator.Emit (OpCodes.Ldarg_0);
|
||||
generator.Emit (OpCodes.Ldarg_1);
|
||||
generator.Emit (OpCodes.And); // arg0 & arg1
|
||||
generator.Emit (OpCodes.Ldc_I4_0);
|
||||
if (typeof (T) == typeof (uint))
|
||||
generator.Emit (OpCodes.Conv_U4);
|
||||
else if (typeof (T) == typeof (long))
|
||||
generator.Emit (OpCodes.Conv_I8);
|
||||
else if (typeof (T) == typeof (ulong))
|
||||
generator.Emit (OpCodes.Conv_U8);
|
||||
|
||||
generator.Emit (OpCodes.Ceq); // pushes 1 if not equal
|
||||
generator.Emit (OpCodes.Ldc_I4_0);
|
||||
generator.Emit (OpCodes.Ceq); // reverses
|
||||
generator.Emit (OpCodes.Ret);
|
||||
return method.CreateDelegate (typeof(Func<T, T, bool>));
|
||||
var left = Expression.Parameter (typeof(T));
|
||||
var right = Expression.Parameter (typeof(T));
|
||||
var hasFlag = Expression.Equal (Expression.And (left, right), right);
|
||||
return Expression.Lambda (hasFlag, left, right).Compile();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -171,13 +153,10 @@ namespace Xamarin.PropertyEditing.Reflection
|
|||
{
|
||||
return OrOperators.GetOrAdd (typeof(T), t => {
|
||||
return Task.Run (() => {
|
||||
DynamicMethod method = new DynamicMethod ("Or", typeof(T), new[] { typeof(T), typeof(T) });
|
||||
ILGenerator generator = method.GetILGenerator ();
|
||||
generator.Emit (OpCodes.Ldarg_0);
|
||||
generator.Emit (OpCodes.Ldarg_1);
|
||||
generator.Emit (OpCodes.Or);
|
||||
generator.Emit (OpCodes.Ret);
|
||||
return method.CreateDelegate (typeof(Func<T, T, T>));
|
||||
var left = Expression.Parameter (typeof(T));
|
||||
var right = Expression.Parameter (typeof(T));
|
||||
var or = Expression.Or (left, right);
|
||||
return Expression.Lambda (or, left, right).Compile ();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче