예제 #1
0
        public override void Initialize()
        {
            var structAttribute = this.ClrType.GetCustomAttribute <FlatBufferStructAttribute>();

            if (structAttribute == null)
            {
                throw new InvalidFlatBufferDefinitionException($"Can't create struct type model from type {this.ClrType.Name} because it does not have a [FlatBufferStruct] attribute.");
            }

            TableTypeModel.EnsureClassCanBeInheritedByOutsideAssembly(this.ClrType, out this.preferredConstructor);

            var properties = this.ClrType
                             .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                             .Select(x => new
            {
                Property  = x,
                Attribute = x.GetCustomAttribute <FlatBufferItemAttribute>() !   // suppress check here; we filter on the next line.
            })
예제 #2
0
        public override void Initialize()
        {
            var structAttribute = this.ClrType.GetCustomAttribute <FlatBufferStructAttribute>();

            if (structAttribute == null)
            {
                throw new InvalidFlatBufferDefinitionException($"Can't create struct type model from type {this.ClrType.Name} because it does not have a [FlatBufferStruct] attribute.");
            }

            TableTypeModel.EnsureClassCanBeInheritedByOutsideAssembly(this.ClrType, out var ctor);

            var properties = this.ClrType
                             .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                             .Select(x => new
            {
                Property  = x,
                Attribute = x.GetCustomAttribute <FlatBufferItemAttribute>()
            })
                             .Where(x => x.Attribute != null)
                             .OrderBy(x => x.Attribute.Index);

            ushort expectedIndex = 0;

            this.inlineSize = 0;

            foreach (var item in properties)
            {
                var propertyAttribute = item.Attribute;
                var property          = item.Property;

                if (propertyAttribute.Deprecated)
                {
                    throw new InvalidFlatBufferDefinitionException($"FlatBuffer struct {this.ClrType.Name} may not have deprecated properties");
                }

                ushort index = propertyAttribute.Index;
                if (index != expectedIndex)
                {
                    throw new InvalidFlatBufferDefinitionException($"FlatBuffer struct {this.ClrType.Name} does not declare an item with index {expectedIndex}. Structs must have sequenential indexes starting at 0.");
                }

                if (!object.ReferenceEquals(propertyAttribute.DefaultValue, null))
                {
                    throw new InvalidFlatBufferDefinitionException($"FlatBuffer struct {this.ClrType.Name} declares default value on index {expectedIndex}. Structs may not have default values.");
                }

                expectedIndex++;
                ITypeModel propertyModel = this.typeModelContainer.CreateTypeModel(property.PropertyType);

                if (!propertyModel.IsValidStructMember || propertyModel.PhysicalLayout.Length > 1)
                {
                    throw new InvalidFlatBufferDefinitionException($"Struct property {property.Name} with type {property.PropertyType.Name} cannot be part of a flatbuffer struct.");
                }

                int propertySize      = propertyModel.PhysicalLayout[0].InlineSize;
                int propertyAlignment = propertyModel.PhysicalLayout[0].Alignment;
                this.maxAlignment = Math.Max(propertyAlignment, this.maxAlignment);

                // Pad for alignment.
                this.inlineSize += SerializationHelpers.GetAlignmentError(this.inlineSize, propertyAlignment);

                StructMemberModel model = new StructMemberModel(
                    propertyModel,
                    property,
                    index,
                    this.inlineSize);

                this.memberTypes.Add(model);
                this.inlineSize += propertyModel.PhysicalLayout[0].InlineSize;
            }
        }
        /// <summary>
        /// Tries to create a type model based on the given type.
        /// </summary>
        public bool TryCreateTypeModel(TypeModelContainer container, Type type, out ITypeModel typeModel)
        {
            if (type == typeof(string))
            {
                typeModel = new StringTypeModel();
                return(true);
            }

            if (type == typeof(SharedString))
            {
                typeModel = new SharedStringTypeModel();
                return(true);
            }

            if (type.IsArray)
            {
                typeModel = new ArrayVectorTypeModel(type, container);
                return(true);
            }

            if (type.IsGenericType)
            {
                var genericDef = type.GetGenericTypeDefinition();
                if (genericDef == typeof(IList <>) || genericDef == typeof(IReadOnlyList <>))
                {
                    typeModel = new ListVectorTypeModel(type, container);
                    return(true);
                }

                if (genericDef == typeof(Memory <>) || genericDef == typeof(ReadOnlyMemory <>))
                {
                    typeModel = new MemoryVectorTypeModel(type, container);
                    return(true);
                }

                if (genericDef == typeof(IIndexedVector <,>))
                {
                    typeModel = new IndexedVectorTypeModel(type, container);
                    return(true);
                }
            }

            if (typeof(IUnion).IsAssignableFrom(type))
            {
                typeModel = new UnionTypeModel(type, container);
                return(true);
            }

            if (type.IsEnum)
            {
                typeModel = new EnumTypeModel(type, container);
                return(true);
            }

            if (Nullable.GetUnderlyingType(type) != null)
            {
                var underlyingType = Nullable.GetUnderlyingType(type);
                if (underlyingType.IsEnum)
                {
                    typeModel = new NullableEnumTypeModel(type, container);
                    return(true);
                }
            }

            var tableAttribute = type.GetCustomAttribute <FlatBufferTableAttribute>();

            if (tableAttribute != null)
            {
                typeModel = new TableTypeModel(type, container);
                return(true);
            }

            var structAttribute = type.GetCustomAttribute <FlatBufferStructAttribute>();

            if (structAttribute != null)
            {
                typeModel = new StructTypeModel(type, container);
                return(true);
            }

            typeModel = null;
            return(false);
        }