예제 #1
0
        /// <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));
            }
        }