internal static List <FieldInfo> GetOrderedFields(Type type, ImmutableSettings settings) { var mustUseReflectionToSetReadonly = FieldInfoModifier.MustUseReflectionToSetReadonly(settings); lock (_cacheLock) { ref var fields = ref _orderedCache.GetOrAddValueRef(new OrderedTypeCacheKey { Type = type, Flattened = settings.FlattenClassHierarchy }); if (fields == null) { var unorderedFields = settings.FlattenClassHierarchy ? GetFlattenedFields(type) : GetFields(type); if (mustUseReflectionToSetReadonly) { fields = unorderedFields.OrderBy(x => IsPrimitive(x.FieldType) ? 0 : 1) .ThenBy(x => x.IsInitOnly ? 0 : 1) .ThenBy(x => x.FieldType == typeof(string) ? 0 : 1) .ThenBy(x => x.Name).ToList(); } else { fields = unorderedFields.OrderBy(x => IsPrimitive(x.FieldType) ? 0 : 1) .ThenBy(x => x.FieldType == typeof(string) ? 0 : 1) .ThenBy(x => x.Name).ToList(); } } return(fields); }
public TypeKey(Type type, ImmutableSettings settings, bool includesTypeInfo, bool isolated) { Type = type; Settings = settings; IncludesTypeInfo = includesTypeInfo; Isolated = isolated; }
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); }
internal static bool MustUseReflectionToSetReadonly(ImmutableSettings settings) => SetFieldInfoNotReadonly == null || settings.ForceReflectionToSetReadonlyFields;