/// <summary> /// Get layout of <typeparamref name="T"/> with padding information ordered by offset. /// </summary> /// <typeparam name="T">To to get structure of.</typeparam> /// <param name="considerPrimitives">Eny type in collection will be considered primitive and will not be splitted into several fields.</param> /// <param name="recursive">If true the resulting list will have fields for all nested types as well.</param> /// <param name="hierarchical">Not implemented yet if specified.</param> public static IReadOnlyList <FieldLayoutBase> GetLayout <T>(bool recursive = true, IReadOnlyCollection <Type> considerPrimitives = null, bool hierarchical = false) where T : struct { if (hierarchical) { throw new NotImplementedException("Could report recursive layout with complex fields in each other"); } var tree = GetLayoutTree <T>(); IEnumerable <FieldLayout> fieldsLayout = GetFieldsLayoutInternal <T>(in tree, recursive, considerPrimitives) .OrderBy(x => x.Offset); var layouts = new List <FieldLayoutBase>(); Padder.AddPaddings(true, Unsafe.SizeOf <T>(), fieldsLayout.OrderBy(x => x.Offset).ToArray(), layouts); return(layouts); }
/// <summary> /// Gets a layout of a given <paramref name="type"/>. /// </summary> public static TypeLayout GetLayout(Type type, TypeLayoutCache?cache = null, bool includePaddings = true) { if (cache != null && cache.LayoutCache.TryGetValue(type, out var result)) { return(result); } try { result = DoGetLayout(); cache?.LayoutCache.TryAdd(type, result); return(result); } catch (Exception e) { Console.WriteLine($"Failed to create an instance of type {type}: {e}."); throw; } TypeLayout DoGetLayout() { var(size, overhead) = TypeInspector.GetSize(type); // fields with no paddings var fieldsAndOffsets = TypeInspector.GetFieldOffsets(type); var fieldsOffsets = fieldsAndOffsets .Select(x => new FieldLayout(x.offset, x.fieldInfo, TypeInspector.GetFieldSize(x.fieldInfo.FieldType))) .ToArray(); var layouts = new List <FieldLayoutBase>(); Padder.AddPaddings(includePaddings, size, fieldsOffsets, layouts); return(new TypeLayout(type, size, overhead, layouts.ToArray(), cache)); } }