Ejemplo n.º 1
0
        private TypeLayout(Type type, int size, int overhead, FieldLayoutBase[] fields, TypeLayoutCache cache)
        {
            Type     = type;
            Size     = size;
            Overhead = overhead;
            Fields   = fields;

            // We can't get padding information for unsafe structs.
            // Assuming there is no one.
            var thisInstancePaddings = type.IsUnsafeValueType() ? 0 : fields.OfType <Padding>().Sum(p => p.Size);

            cache = cache ?? TypeLayoutCache.Create();

            var nestedPaddings = fields
                                 // Need to include paddings for value types only
                                 // because we can't tell if the reference is exclusive or shared.
                                 .OfType <FieldLayout>()
                                 // Primitive types can be recursive.
                                 .Where(fl => fl.FieldInfo.FieldType.IsValueType && !fl.FieldInfo.FieldType.IsPrimitive)
                                 .Select(fl => GetLayout(fl.FieldInfo.FieldType, cache, includePaddings: true))
                                 .Sum(tl => tl.Paddings);

            Paddings = thisInstancePaddings + nestedPaddings;

            // Updating the cache.
            cache.LayoutCache.AddOrUpdate(type, this, (t, layout) => layout);
        }
Ejemplo n.º 2
0
        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
            {
                Console.WriteLine($"Failed to create an instance of type {type}");
                throw;
            }

            TypeLayout DoGetLayout()
            {
                var(size, overhead) = InspectorHelper.GetSize(type);

                var fieldsOffsets = InspectorHelper.GetFieldOffsets(type);
                var fields        = new List <FieldLayoutBase>();

                if (includePaddings && fieldsOffsets.Length != 0 && fieldsOffsets[0].offset != 0)
                {
                    fields.Add(new Padding(fieldsOffsets[0].offset, 0));
                }

                for (var index = 0; index < fieldsOffsets.Length; index++)
                {
                    var fieldOffset = fieldsOffsets[index];
                    var fieldInfo   = new FieldLayout(fieldOffset.offset, fieldOffset.fieldInfo);
                    fields.Add(fieldInfo);

                    if (includePaddings)
                    {
                        int nextOffsetOrSize = size;
                        if (index != fieldsOffsets.Length - 1)
                        {
                            // This is not a last field.
                            nextOffsetOrSize = fieldsOffsets[index + 1].offset;
                        }

                        var nextSectionOffsetCandidate = fieldInfo.Offset + fieldInfo.Size;
                        if (nextSectionOffsetCandidate < nextOffsetOrSize)
                        {
                            // we have padding
                            fields.Add(new Padding(nextOffsetOrSize - nextSectionOffsetCandidate, nextSectionOffsetCandidate));
                        }
                    }
                }

                return(new TypeLayout(type, size, overhead, fields.ToArray(), cache));
            }
        }
Ejemplo n.º 3
0
        public static TypeLayout?TryGetLayout(Type type, TypeLayoutCache cache)
        {
            if (type.CanCreateInstance())
            {
                return(GetLayout(type, cache));
            }

            return(null);
        }
Ejemplo n.º 4
0
        /// <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));
            }
        }
Ejemplo n.º 5
0
 public static TypeLayout GetLayout <T>(TypeLayoutCache cache = null, bool includePaddings = true)
 {
     return(GetLayout(typeof(T), cache, includePaddings));
 }