예제 #1
0
        /// <summary>
        /// Reads the current chunk and creates a runtime type for it, which is then returned.
        /// </summary>
        /// <param name="context">The context of the chunk file being read. Must not be null.</param>
        /// <returns>Returns null if there was no runtime type found for the current chunk.</returns>
        public override object Read(ChunkFileContext context)
        {
            Check.IfArgumentNull(context, nameof(context));
            Check.IfArgumentNull(context.ChunkStack, nameof(context.ChunkStack));
            Check.IfArgumentNull(context.ChunkStack.CurrentChunk, nameof(context.ChunkStack.CurrentChunk));
            Check.IfArgumentNull(context.ChunkFile, nameof(context.ChunkFile));
            Check.IfArgumentNull(context.ChunkFile.BaseStream, nameof(context.ChunkFile.BaseStream));

            var reader = context.Services.GetService <FileChunkReader>();
            var stream = context.ChunkFile.BaseStream;

            var chunk = context.ChunkStack.CurrentChunk;

            chunk.RuntimeInstance = reader.ReadRuntimeChunkType(stream, chunk.ChunkId);

            // extra check if type returned is correct for chunk.
            if (chunk.RuntimeInstance != null &&
                !ChunkAttribute.GetChunkId(chunk.RuntimeInstance).MatchesWith(chunk.ChunkId.ToString()))
            {
                var msg = String.Format(
                    CultureInfo.InvariantCulture,
                    "The type '{0}' tagged with '{1}' was returned when '{2}' was requested.",
                    chunk.RuntimeInstance.GetType(),
                    ChunkAttribute.GetChunkId(chunk.RuntimeInstance),
                    chunk.ChunkId);

                throw new ChunkFileException(msg);
            }

            return(chunk.RuntimeInstance);
        }
        public ChunkFileContextBuilder AddChunk(Type chunkType)
        {
            var chunkId = ChunkAttribute.GetChunkId(chunkType);

            if (String.IsNullOrEmpty(chunkId))
            {
                throw new ArgumentException($"The specified type {chunkType.Name} has no ChunkAttribute.", nameof(chunkType));
            }
            _chunkTypes.Add(chunkType);
            return(this);
        }
예제 #3
0
        public FileChunkHeader WriteNextChunk(object chunk)
        {
            Contract.Requires(chunk != null);
            Check.IfArgumentNull(chunk, "chunk");

            // find chunk id
            var chunkId = ChunkAttribute.GetChunkId(chunk);

            if (String.IsNullOrEmpty(chunkId))
            {
                var msg = String.Format(
                    CultureInfo.InvariantCulture,
                    "No Chunk Attribute was found for the specified runtime object of type '{0}'.",
                    chunk.GetType().FullName);

                throw new ArgumentException(msg);
            }

            if (chunkId.HasWildcard())
            {
                // TODO: this must be pluggable in some way
                // for now only digits
                chunkId = chunkId.Merge("0000");
            }

            var chunkTypeId  = new FourCharacterCode(chunkId);
            var chunkHandler = this.handlerMgr.GetChunkHandler(chunkTypeId);

            if (!chunkHandler.CanWrite(chunk))
            {
                var msg = String.Format(
                    CultureInfo.InvariantCulture,
                    "The chunk handler '{0}' cannot write the specified runtime object.",
                    chunkHandler.ChunkId);

                throw new ArgumentException(msg);
            }

            int stackPos = this.context.HeaderStack.Count;
            var header   = this.PushNewHeader(chunkTypeId);

            chunkHandler.Write(this.context, chunk);

            // wind down the stack to the level it was before we started.
            while (this.context.HeaderStack.Count > stackPos)
            {
                var poppedHeader = this.PopHeader();
                this.WriteChunkHeader(poppedHeader);
            }

            return(header);
        }
예제 #4
0
        /// <summary>
        /// Scans the <paramref name="assembly"/> for types that have the
        /// <see cref="ChunkAttribute"/> applied and adds them to the factory.
        /// </summary>
        /// <param name="assembly">Must not be null.</param>
        /// <param name="replace">If true the Type found in the <paramref name="assembly"/> will replace
        /// an already registered type.</param>
        public void AddChunksFrom(Assembly assembly, AddMode addMode)
        {
            Check.IfArgumentNull(assembly, nameof(assembly));

            var result = from type in assembly.GetTypes()
                         where type.IsClass && type.IsChunk()
                         select new { ChunkId = ChunkAttribute.GetChunkId(type), Type = type };

            foreach (var item in result)
            {
                AddChunkType(item.ChunkId, item.Type, addMode);
            }
        }
예제 #5
0
        private static string GetCollectionItemChunkId(object instance)
        {
            Type type     = instance.GetType();
            Type dataType = null;

            if (type.IsGenericType)
            {
                var genType = type.GetGenericTypeDefinition();

                if (genType.FullName.StartsWith("System.Collections.Generic.", StringComparison.OrdinalIgnoreCase) &&
                    genType.FullName.EndsWith("`1", StringComparison.OrdinalIgnoreCase))
                {
                    dataType = (from typeArg in type.GetGenericArguments()
                                select typeArg).FirstOrDefault();
                }
                else
                {
                    var msg = String.Format(
                        CultureInfo.InvariantCulture,
                        "The generic type '{0}' is not supported. Use IEnumerable<T> for collections.",
                        genType.FullName);

                    throw new NotSupportedException(msg);
                }
            }
            else
            {
                dataType = type;
            }

            string chunkId = null;

            if (dataType != null)
            {
                chunkId = ChunkAttribute.GetChunkId(dataType);
            }

            return(chunkId);
        }
예제 #6
0
        public override void Write(ChunkFileContext context, object instance)
        {
            Check.IfArgumentNull(context, "context");
            Check.IfArgumentNull(instance, "instance");
            Check.IfArgumentNotOfType <RiffChunk>(instance, "instance");

            var chunk = (RiffChunk)instance;

            if (chunk.InnerChunk == null)
            {
                throw new ArgumentException("No RIFF chunk content found.", "instance");
            }

            // make sure the correct file type is set.
            chunk.FileType = new FourCharacterCode(ChunkAttribute.GetChunkId(chunk.InnerChunk));

            // write out RIFF file type
            base.Write(context, instance);

            var writer = context.CompositionContainer.GetService <FileChunkWriter>();

            writer.WriteRuntimeChunkType(chunk.InnerChunk);
        }
예제 #7
0
        public bool WriteChunkObject(object value)
        {
            Contract.Requires(value != null);
            Check.IfArgumentNull(value, "runtimeObject");

            bool isCollection = false;
            var  type         = value.GetType();

            if (type.IsGenericType)
            {
                // use generic parameter as type
                type = (from typeArg in type.GetGenericArguments()
                        select typeArg).FirstOrDefault();

                if (type == null)
                {
                    throw new ChunkFileException("Internal error. No type argument from generic type.");
                }

                isCollection = true;
            }

            var chunkId = ChunkAttribute.GetChunkId(type);

            foreach (var member in this.members)
            {
                if (member.ChunkMatches(chunkId) &&
                    member.CanSetValue)
                {
                    member.SetValue(this.Instance, value, isCollection);

                    return(true);
                }
            }

            return(false);
        }
예제 #8
0
        private static IEnumerable <ObjectMemberData> BuildMemberList(Type type)
        {
            Contract.Requires(type != null);
            Check.IfArgumentNull(type, "type");

            var members = (from member in type.GetMembers()
                           where member.MemberType == MemberTypes.Property || member.MemberType == MemberTypes.Field
                           where member.GetCustomAttributes(typeof(IgnoreAttribute), true).Length == 0
                           select new ObjectMemberData {
                FieldInfo = member as FieldInfo, PropertyInfo = member as PropertyInfo
            }).ToList();

            foreach (var member in members)
            {
                Contract.Assume(member != null);

                string chunkId  = null;
                Type   dataType = null;

                if (member.FieldInfo != null)
                {
                    dataType = member.FieldInfo.FieldType;
                }

                if (member.PropertyInfo != null)
                {
                    dataType = member.PropertyInfo.PropertyType;
                }

                Contract.Assume(dataType != null);

                if (dataType.IsGenericType)
                {
                    var genType = dataType.GetGenericTypeDefinition();

                    if (genType.FullName.StartsWith("System.Collections.Generic.", StringComparison.OrdinalIgnoreCase) &&
                        genType.FullName.EndsWith("`1", StringComparison.OrdinalIgnoreCase))
                    {
                        member.DataType = (from typeArg in dataType.GetGenericArguments()
                                           select typeArg).FirstOrDefault();
                        member.IsCollection = true;
                    }
                    else
                    {
                        var msg = String.Format(
                            CultureInfo.InvariantCulture,
                            "The generic type '{0}' is not supported. Use IEnumerable<T> for collections.",
                            genType.FullName);

                        throw new NotSupportedException(msg);
                    }
                }
                else
                {
                    member.DataType = dataType;
                }

                if (member.DataType != null)
                {
                    chunkId = ChunkAttribute.GetChunkId(member.DataType);
                }

                if (!String.IsNullOrEmpty(chunkId))
                {
                    member.ChunkIds = new List <string>();
                    member.ChunkIds.Add(chunkId);
                }
                else
                {
                    var memberInfo = member.GetMemberInfo();

                    if (memberInfo != null)
                    {
                        var chunkTypes = ChunkTypeAttribute.GetChunkTypes(memberInfo);

                        if (chunkTypes != null && chunkTypes.Length > 0)
                        {
                            member.ChunkIds = new List <string>(chunkTypes);
                        }

                        member.ChunkIdsAreChunkTypes = true;
                    }
                }
            }

            return(members);
        }
예제 #9
0
        public void AddChunkType(Type chunkType, AddMode addMode)
        {
            var chunkId = ChunkAttribute.GetChunkId(chunkType);

            AddChunkType(chunkId, chunkType, addMode);
        }