private static Expression GetSizeExpression(Type type, Expression memory, Expression access) { var specificSizeExpression = GetSpecificSizeExpression(type, memory, access); if (specificSizeExpression != null) { return(specificSizeExpression); } if (type.IsArray) { return(Expression.Call(memory, "GetSizeOfSealedInternal", new Type[] { type }, access)); } if (type.IsSealed) { if (type.IsValueType) { var fields = TypeFields.GetFields(type); var all = GetReferenceSizes(fields, access, memory).Aggregate((Expression)Expression.Constant(0L), (x, y) => Expression.Add(x, y)); return(Expression.Add(all, Expression.Constant(GetSizeOfType(type)))); } return(Expression.Call(memory, "GetSizeOfSealedInternal", new Type[] { type }, access)); } else { return(Expression.Call(memory, "GetSizeOfInternal", Array.Empty <Type>(), access)); } }
public void SetFormat(string fieldName, Type fieldType, string format, int width) { if (!string.IsNullOrWhiteSpace(fieldName)) { if (!string.IsNullOrWhiteSpace(format)) { if (!FormatFields.ContainsKey(fieldName)) { FormatFields.Add(fieldName, format); } } if (fieldType != null) { if (!TypeFields.ContainsKey(fieldName)) { TypeFields.Add(fieldName, fieldType); } } if (width > 0) { if (!SizeFields.ContainsKey(fieldName)) { SizeFields.Add(fieldName, width); } } } }
internal static bool IsBlittable(Type elementType) { return(_isBlittableCache.GetOrAdd(elementType, _ => { if (!elementType.IsValueType) { return false; } if (!TypeFields.IsPrimitive(elementType)) { return false; } try { WriteArrayOfValuesMethod1.MakeGenericMethod(elementType); return true; } catch { return false; } })); }
private static IEnumerable <Expression> GetReferenceSizes(List <FieldInfo> fields, Expression source, Expression memory) { foreach (var field in fields) { var fieldType = field.FieldType; if (fieldType.IsPrimitive || fieldType.IsPointer) { continue; } var subSource = Expression.MakeMemberAccess(source, field); if (fieldType.IsValueType && !(fieldType == typeof(ValueTask) || (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(ValueTask <>)))) { var fieldTypeFields = TypeFields.GetFields(fieldType); var subSizes = GetReferenceSizes(fieldTypeFields, subSource, memory); foreach (var subResult in subSizes) { yield return(subResult); } } else { yield return(GetSizeExpression(fieldType, memory, subSource)); } } }
public IFieldBuilder DefineField(string name, IType fieldType, FieldAttributes attributes) { var builder = new AsmFieldBuilder(this, fieldType, attributes, name); TypeFields.Add(builder); return(builder); }
internal bool IsTypeSerializable(Type type) { if (type.IsGenericType && !type.IsGenericTypeDefinition) { type = type.GetGenericTypeDefinition(); if (_autoWhitelistedTypes.Contains(type)) { return(true); } } if (type == typeof(FieldInfoModifier.TestReadonly)) { return(true); } if (type.IsArray) { return(true); } if (typeof(Delegate).IsAssignableFrom(type)) { return(true); } if (typeof(Type).IsAssignableFrom(type)) { return(true); } if (type.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) != null) { return(true); } if (TypeFields.IsPrimitive(type)) { return(true); } if (IsSpecialCoreType(type)) { return(true); } if (_autoWhitelistedTypes.Contains(type)) { return(true); } var declaringTypeIsSerializeable = type.DeclaringType != null && IsTypeSerializable(type.DeclaringType); return(declaringTypeIsSerializeable || WhitelistedTypes.Contains(type) || WhitelistFuncs.Any(x => x(type))); }
private static Expression?WriteArray(Type type, ParameterExpression stream, ParameterExpression output, Expression actualSource, ImmutableSettings settings, ImmutableHashSet <Type> visitedTypes, int depth) { if (type.IsArray) { var elementType = type.GetElementType() !; var dimensions = type.GetArrayRank(); var(elementSize, isRef) = TypeFields.GetSizeForType(elementType); var lengths = new List <ParameterExpression>(); for (int i = 0; i < dimensions; ++i) { lengths.Add(Expression.Variable(typeof(int), $"length{i}")); } var statements = new List <Expression>(); statements.Add(ReserveConstantSize(stream, 4 * dimensions)); statements.AddRange(lengths.Select((x, i) => Expression.Assign(x, Expression.Call(actualSource, "GetLength", Array.Empty <Type>(), Expression.Constant(i))))); statements.AddRange(lengths.Select(x => Expression.Call(stream, BinaryStreamMethods <TStream> .GenericMethods <int> .WriteValueMethodInfo, x))); // don't write anything else if lengths are zero var skipLabel = Expression.Label("skipWrite"); statements.Add( Expression.IfThen( Expression.Equal(Expression.Constant(0), lengths.Aggregate((Expression)Expression.Empty(), (a, b) => a.NodeType == ExpressionType.Default ? (Expression)b : Expression.Or(a, b))), Expression.Goto(skipLabel) ) ); if (IsBlittable(elementType) && dimensions < 3) { statements.Add(WriteArrayOfBlittableValues(output, actualSource, stream, dimensions, elementType, elementSize)); } else { statements.Add(WriteArrayGeneral(output, actualSource, stream, dimensions, lengths, elementType, elementSize, settings, visitedTypes, depth)); } statements.Add(Expression.Label(skipLabel)); return(Expression.Block(lengths, statements)); } return(null); }
private void ReadEmbedded(UnityBinaryReader reader, int version, int typeVersion) { int fieldCount = reader.ReadInt32(); int stringTableLength = reader.ReadInt32(); TypeFields.Capacity = fieldCount; TypeFields.Clear(); for (int i = 0; i < fieldCount; i++) { var field = new Field(reader); TypeFields.Add(field); } ReadStringTable(reader, stringTableLength); }
public void Can_use_TypedFields_accessor() { var runtimeType = typeof(MyType); var typeProps = TypeFields.Get(runtimeType); //Equivalent to: // typeProps = TypeFields<MyType>.Instance; var instance = runtimeType.CreateInstance(); var propAccessor = typeProps.GetAccessor("LongField"); propAccessor.PublicSetter(instance, 1L); Assert.That(propAccessor.PublicGetter(instance), Is.EqualTo(1)); typeProps.GetPublicSetter("StringField")(instance, "foo"); var value = typeProps.GetPublicGetter("StringField")(instance); Assert.That(value, Is.EqualTo("foo")); }
private static object PropValue(object targetValue, Type targetType, string name) { var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name) ?? TypeFields.Get(targetType).GetPublicGetter(name); if (memberFn != null) { return(memberFn(targetValue)); } var indexerMethod = targetType.GetInstanceMethod("get_Item"); if (indexerMethod != null) { var fn = indexerMethod.GetInvoker(); var ret = fn(targetValue, name); return(ret ?? JsNull.Value); } throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field"); }
private static bool HasNoReferences(Type elementType) { if (!elementType.IsSealed || elementType.IsInterface || elementType.IsAbstract) { return(false); } if (elementType == typeof(string)) { return(false); } if (elementType.IsArray) { return(false); } var fields = TypeFields.GetFields(elementType); return(fields.All(x => x.FieldType.IsPrimitive || x.FieldType.IsValueType && HasNoReferences(x.FieldType))); }
public static T ConvertToValueTuple <T>(this IDataReader reader, object[] values, IOrmLiteDialectProvider dialectProvider) { var row = typeof(T).CreateInstance(); var typeFields = TypeFields.Get(typeof(T)); values = reader.PopulateValues(values, dialectProvider); for (var i = 0; i < reader.FieldCount; i++) { var itemName = $"Item{(i + 1)}"; var field = typeFields.GetAccessor(itemName); if (field == null) { break; } var dbValue = values != null ? values[i] : reader.GetValue(i); if (dbValue == null) { continue; } var fieldType = field.FieldInfo.FieldType; if (dbValue.GetType() == fieldType) { field.PublicSetterRef(ref row, dbValue); } else { var converter = dialectProvider.GetConverter(fieldType); var fieldValue = converter.FromDbValue(fieldType, dbValue); field.PublicSetterRef(ref row, fieldValue); } } return((T)row); }
private static object PropValue(object targetValue, Type targetType, string name) { var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name) ?? TypeFields.Get(targetType).GetPublicGetter(name); if (memberFn != null) { return(memberFn(targetValue)); } var methods = targetType.GetInstanceMethods(); var indexerMethod = methods.FirstOrDefault(x => x.Name == "get_Item" && x.GetParameters().Any(p => p.ParameterType == typeof(string))) ?? methods.FirstOrDefault(x => x.Name == "get_Item" && x.GetParameters().Any(p => p.ParameterType != typeof(string))); if (indexerMethod != null) { var fn = indexerMethod.GetInvoker(); var ret = fn(targetValue, name); return(ret); } throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field"); }
private object GetValue(object targetValue, TemplateScopeContext scope) { if (targetValue == null || targetValue == JsNull.Value) { return(JsNull.Value); } var targetType = targetValue.GetType(); try { object propValue(string name) { var memberFn = TypeProperties.Get(targetType).GetPublicGetter(name) ?? TypeFields.Get(targetType).GetPublicGetter(name); if (memberFn != null) { return(memberFn(targetValue)); } var indexerMethod = targetType.GetInstanceMethod("get_Item"); if (indexerMethod != null) { var fn = indexerMethod.GetInvoker(); var ret = fn(targetValue, name); return(ret ?? JsNull.Value); } throw new ArgumentException($"'{targetType.Name}' does not have a '{name}' property or field"); } if (!Computed) { if (Property is JsIdentifier identifier) { var ret = propValue(identifier.NameString); // Don't emit member expression on null KeyValuePair if (ret == null && targetType.Name == "KeyValuePair`2") { return(JsNull.Value); } return(ret); } } else { var indexValue = Property.Evaluate(scope); if (indexValue == null) { return(JsNull.Value); } if (targetType.IsArray) { var array = (Array)targetValue; if (indexValue is long l) { return(array.GetValue(l)); } var intValue = indexValue.ConvertTo <int>(); return(array.GetValue(intValue)); } if (targetValue is IDictionary dict) { var ret = dict[indexValue]; return(ret ?? JsNull.Value); } if (indexValue is string propName) { return(propValue(propName)); } if (targetValue is IList list) { var intValue = indexValue.ConvertTo <int>(); return(list[intValue]); } if (targetValue is IEnumerable e) { var intValue = indexValue.ConvertTo <int>(); var i = 0; foreach (var item in e) { if (i++ == intValue) { return(item); } } return(null); } if (DynamicNumber.IsNumber(indexValue.GetType())) { var indexerMethod = targetType.GetInstanceMethod("get_Item"); if (indexerMethod != null) { var fn = indexerMethod.GetInvoker(); var ret = fn(targetValue, indexValue); return(ret ?? JsNull.Value); } } } } catch (KeyNotFoundException) { return(JsNull.Value); } catch (Exception ex) { var exResult = scope.PageResult.Format.OnExpressionException(scope.PageResult, ex); if (exResult != null) { return(exResult); } var expr = ToRawString(); throw new BindingExpressionException($"Could not evaluate expression '{expr}'", null, expr, ex); } throw new NotSupportedException($"'{targetValue.GetType()}' does not support access by '{Property}'"); }
private static Delegate GenerateMethodImpl(Type type, bool isVirtual) { var source = Expression.Parameter(isVirtual ? typeof(object) : type, "obj"); var memory = Expression.Parameter(typeof(Memory), "memory"); var statements = new List <Expression>(); var localVariables = new List <ParameterExpression>(); var castedSource = source; if (isVirtual) { castedSource = Expression.Variable(type); localVariables.Add(castedSource); statements.Add(Expression.Assign(castedSource, Expression.Convert(source, type))); } var result = Expression.Variable(typeof(long), "result"); localVariables.Add(result); statements.Add(Expression.Assign(result, Expression.Constant(0L))); var specificSizeExpression = GetSpecificSizeExpression(type, memory, castedSource); if (specificSizeExpression != null) { statements.Add(Expression.AddAssign(result, specificSizeExpression)); } else { if (type == typeof(string)) { statements.Add(Expression.AddAssign(result, Expression.Condition( Expression.ReferenceEqual(castedSource, Expression.Constant(null)), Expression.Constant(0L), Expression.Condition( Expression.Equal(Expression.Property(castedSource, "Length"), Expression.Constant(0)), Expression.Constant(0L), Expression.Convert( Expression.And(Expression.Constant(0b11111100), Expression.Add(Expression.Constant(IntPtr.Size * 4), Expression.Multiply(Expression.Constant(2), Expression.Property(castedSource, "Length"))) ), typeof(long)) ) ))); } else if (type.IsArray) { statements.Add(Expression.AddAssign(result, Expression.Constant((long)IntPtr.Size * 3))); var elementType = type.GetElementType(); var dimensions = type.GetArrayRank(); var lengths = new List <ParameterExpression>(); for (int i = 0; i < dimensions; ++i) { lengths.Add(Expression.Variable(typeof(int))); } var loopExpressions = new List <Expression>(); loopExpressions.AddRange(lengths.Select((x, i) => Expression.Assign(x, Expression.Call(castedSource, "GetLength", Array.Empty <Type>(), Expression.Constant(i))))); if (HasNoReferences(elementType)) { loopExpressions.Add( Expression.AddAssign(result, lengths.Select(x => Expression.Convert(x, typeof(long))).Aggregate((Expression)Expression.Constant(GetSizeOfType(elementType)), (x, y) => Expression.Multiply(x, y)))); statements.Add(Expression.Block(lengths, loopExpressions)); } else { loopExpressions.Add(Expression.AddAssign(result, lengths.Select(x => Expression.Convert(x, typeof(long))).Aggregate((Expression)Expression.Constant((long)IntPtr.Size), (x, y) => Expression.Multiply(x, y)))); var indices = new List <ParameterExpression>(); var breakLabels = new List <LabelTarget>(); var continueLabels = new List <LabelTarget>(); for (int i = 0; i < dimensions; ++i) { indices.Add(Expression.Variable(typeof(int))); breakLabels.Add(Expression.Label()); continueLabels.Add(Expression.Label()); } var accessExpression = dimensions > 1 ? (Expression)Expression.ArrayIndex(castedSource, indices) : Expression.ArrayIndex(castedSource, indices[0]); Expression getSize = Expression.AddAssign(result, GetSizeExpression(elementType, memory, accessExpression)); var loop = getSize; for (int i = 0; i < dimensions; ++i) { loop = Expression.Block( Expression.Assign(indices[i], Expression.Constant(0)), Expression.Loop(Expression.IfThenElse( Expression.GreaterThanOrEqual(indices[i], lengths[i]), Expression.Break(breakLabels[i]), Expression.Block(loop, Expression.Label(continueLabels[i]), Expression.Assign(indices[i], Expression.Increment(indices[i]))) ), breakLabels[i]) ); } loopExpressions.Add(Expression.Block(indices, loop)); statements.Add(Expression.Block(lengths, loopExpressions)); } } else { statements.Add(Expression.AddAssign(result, Expression.Constant(GetSizeOfType(type)))); var fields = TypeFields.GetFields(type); statements.AddRange(GetReferenceSizes(fields, castedSource, memory).Select(x => Expression.AddAssign(result, x))); } statements.Add(result); } var lambda = Expression.Lambda(Expression.Block(localVariables, statements), $"Apex.Runtime.Memory_SizeOf_{type.FullName}", new[] { source, memory }).Compile(); return(lambda); }