示例#1
0
        public static void ToStream <TItem>(Stream stream, TItem item, CollectionSchema collectionSchema = null)
        {
            var bufferedStream = new BufferedStream(stream);


            var useProtocolBuffers =
                collectionSchema == null; // use protocol buffers only for requests not for business objects
            var useCompression = collectionSchema != null && collectionSchema.UseCompression;

            var mode = SerializationMode.ProtocolBuffers;

            if (!useProtocolBuffers)
            {
                mode = SerializationMode.Json;
            }

            var writer = new BinaryWriter(bufferedStream);

            const int itemCount = 1;

            writer.Write(itemCount);
            var data = SerializationHelper.ObjectToBytes(item, mode, useCompression);

            writer.Write(useProtocolBuffers);
            writer.Write(useCompression);
            writer.Write(0D);
            writer.Write(data.Length);
            writer.Write(data);
            writer.Flush();
        }
示例#2
0
        public static PackedObject Pack <TObject>(TObject instance, [NotNull] CollectionSchema typeDescription, string collectionName = null)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }
            if (typeDescription == null)
            {
                throw new ArgumentNullException(nameof(typeDescription));
            }


            var result = new PackedObject
            {
                // scalar values that are visible server-side
                Values = new KeyValue[typeDescription.ServerSide.Count(k => !k.IsCollection)],
                // vector values that are visible server-side
                CollectionValues = new KeyValues[typeDescription.ServerSide.Count(k => k.IsCollection)]
            };


            // process server-side values
            var pos           = 0;
            var collectionPos = 0;

            foreach (var metadata in typeDescription.ServerSide)
            {
                var getter = ExpressionTreeHelper.Getter <TObject>(metadata.Name);
                var value  = getter(instance);

                if (!metadata.IsCollection)
                {
                    // if the primary key is an empty Guid generate a value
                    if (metadata.IndexType == IndexType.Primary)
                    {
                        if (Guid.Empty.Equals(value))
                        {
                            value = Guid.NewGuid();
                        }
                    }

                    result.Values[pos++] = new KeyValue(value, metadata);
                }
                else
                {
                    if (value is IEnumerable values && !(value is string))
                    {
                        if (metadata.IndexType == IndexType.Ordered)
                        {
                            throw new NotSupportedException($"The property {metadata.Name} is a collection. It can be indexed as a dictionary but not as an ordered index");
                        }

                        var keyValues = values.Cast <object>().Select(v => new KeyValue(v, metadata));
                        result.CollectionValues[collectionPos++] = new KeyValues(metadata.Name, keyValues);
                    }
示例#3
0
        /// <summary>
        ///     Factory method used to create a precompiled type description.
        ///     This version of the method uses a tagged type ( Attributes are attached to the public properties
        ///     which are indexed in the cache)
        ///     In order to be cacheable, a type must be serializable and must have exactly one primary key
        ///     Optionally it can have multiple unique keys and index keys
        /// </summary>
        /// <param name="type"> type to register (must be properly decorated) </param>
        /// <returns> not null type description if successful </returns>
        public static CollectionSchema FromType(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }


            var useCompression = false;
            var storage        = type.GetCustomAttributes(typeof(StorageAttribute), false).FirstOrDefault();

            if (storage != null)
            {
                var storageParams = (StorageAttribute)storage;
                useCompression = storageParams.UseCompression;
            }

            var result = new CollectionSchema
            {
                UseCompression = useCompression,
                CollectionName = type.Name
            };

            var props = type.GetProperties();

            foreach (var info in props)
            {
                var key = BuildPropertyMetadata(info);
                if (key != null)
                {
                    result.ServerSide.Add(key);
                }

                var fullText = info.GetCustomAttributes(typeof(FullTextIndexationAttribute), true)
                               .FirstOrDefault();

                if (fullText != null)
                {
                    result.FullText.Add(info.Name);
                }
            }


            // Adjust order. Line numbers give relative order of keys but they need to be adjusted to a continuous range with the primary key at index 0 and the collections at the end
            var lineNumbers = new HashSet <int>();

            foreach (var keyInfo in result.ServerSide)
            {
                lineNumbers.Add(keyInfo.Order);
            }


            var lineNumberByPosition = lineNumbers.OrderBy(x => x).ToList();

            foreach (var keyInfo in result.ServerSide)
            {
                var adjustedOrder = lineNumberByPosition.FindIndex(l => l == keyInfo.Order);
                keyInfo.Order = adjustedOrder;
            }


            result.ServerSide = result.ServerSide.OrderBy(k => k.Order).ToList();



            //check if the newly registered type is valid
            if (result.PrimaryKeyField == null)
            {
                throw new NotSupportedException($"No primary key defined for type {type}");
            }


            return(result);
        }
示例#4
0
 internal FluentToken(CollectionSchema schema)
 {
     Product = schema;
 }