예제 #1
0
        /// <summary>
        /// Gets a ContentTypeWriter for the given type.
        /// </summary>
        /// <param name="type">The type of the object to write.</param>
        /// <returns>The ContentTypeWriter for the type.</returns>
        internal ContentTypeWriter GetTypeWriter(Type type)
        {
            ContentTypeWriter typeWriter = null;

            if (!typeMap.TryGetValue(type, out typeWriter))
            {
                int index = typeWriters.Count;
                typeWriter = compiler.GetTypeWriter(type);
                typeWriters.Add(typeWriter);

                if (!typeWriterMap.ContainsKey(typeWriter.GetType()))
                {
                    typeWriterMap.Add(typeWriter.GetType(), index);
                }

                typeMap.Add(type, typeWriter);

                // TODO: This is kinda messy.. seems like there could
                // be a better way for generics and arrays to register
                // their inner types with the typeWriterMap.
                if (type.IsGenericType)
                {
                    var args = type.GetGenericArguments();
                    foreach (var arg in args)
                    {
                        GetTypeWriter(arg);
                    }
                }
                else if (type.IsArray)
                {
                    GetTypeWriter(type.GetElementType());
                }
            }
            return(typeWriter);
        }
예제 #2
0
        /// <summary>
        /// Retrieves the worker writer for the specified type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>The worker writer.</returns>
        /// <remarks>This should be called from the ContentTypeWriter.Initialize method.</remarks>
        public ContentTypeWriter GetTypeWriter(Type type)
        {
            ContentTypeWriter result   = null;
            var  contentTypeWriterType = typeof(ContentTypeWriter <>).MakeGenericType(type);
            Type typeWriterType;

            if (!typeWriterMap.TryGetValue(contentTypeWriterType, out typeWriterType))
            {
                var inputTypeDef = type.GetGenericTypeDefinition();

                Type chosen = null;
                foreach (var kvp in typeWriterMap)
                {
                    var args = kvp.Key.GetGenericArguments();

                    if (args.Length == 0)
                    {
                        continue;
                    }

                    if (!args[0].IsGenericType)
                    {
                        continue;
                    }

                    // Compare generic type definition
                    var keyTypeDef = args[0].GetGenericTypeDefinition();
                    if (inputTypeDef.Equals(keyTypeDef))
                    {
                        chosen = kvp.Value;
                        break;
                    }
                }

                try
                {
                    var concreteType = type.GetGenericArguments();
                    result = (ContentTypeWriter)Activator.CreateInstance(chosen.MakeGenericType(concreteType));

                    // save it for next time.
                    typeWriterMap.Add(contentTypeWriterType, result.GetType());
                }
                catch (Exception)
                {
                    throw new InvalidContentException(String.Format("Could not find ContentTypeWriter for type '{0}'", type.Name));
                }
            }
            else
            {
                result = (ContentTypeWriter)Activator.CreateInstance(typeWriterType);
            }

            if (result != null)
            {
                MethodInfo dynMethod = result.GetType().GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance);
                dynMethod.Invoke(result, new object[] { this });
            }
            return(result);
        }
        /// <summary>
        /// Gets a ContentTypeWriter for the given type.
        /// </summary>
        /// <param name="type">The type of the object to write.</param>
        /// <returns>The ContentTypeWriter for the type.</returns>
        internal ContentTypeWriter GetTypeWriter(Type type)
        {
            ContentTypeWriter typeWriter = null;

            if (!typeMap.TryGetValue(type, out typeWriter))
            {
                int index = typeWriters.Count;
                typeWriter = compiler.GetTypeWriter(type);

                typeWriters.Add(typeWriter);
                if (!typeWriterMap.ContainsKey(typeWriter.GetType()))
                {
                    typeWriterMap.Add(typeWriter.GetType(), index);
                }

                typeMap.Add(type, typeWriter);

                typeWriter.OnAddedToContentWriter(this);
            }
            return(typeWriter);
        }
예제 #4
0
        /// <summary>
        /// Gets a ContentTypeWriter for the given type.
        /// </summary>
        /// <param name="type">The type of the object to write.</param>
        /// <returns>The ContentTypeWriter for the type.</returns>
        internal ContentTypeWriter GetTypeWriter(Type type)
        {
            ContentTypeWriter typeWriter = null;

            if (!typeMap.TryGetValue(type, out typeWriter))
            {
                int index = typeWriters.Count;
                typeWriter = compiler.GetTypeWriter(type);
                typeWriters.Add(typeWriter);
                if (!typeWriterMap.ContainsKey(typeWriter.GetType()))
                {
                    typeWriterMap.Add(typeWriter.GetType(), index);
                }
                typeMap.Add(type, typeWriter);

                var args = type.GetGenericArguments();
                foreach (var arg in args)
                {
                    GetTypeWriter(arg);
                }
            }
            return(typeWriter);
        }
예제 #5
0
        /// <summary>
        /// Writes a single object to the output binary, using the specified type hint and writer worker.
        /// </summary>
        /// <typeparam name="T">The type of value.</typeparam>
        /// <param name="value">The value to write.</param>
        /// <param name="typeWriter">The content type writer.</param>
        /// <remarks>The type hint should be retrieved from the Initialize method of the ContentTypeWriter
        /// that is calling WriteObject, by calling GetTypeWriter and passing it the type of the field used
        /// to hold the value being serialized.
        /// </remarks>
        public void WriteObject <T>(T value, ContentTypeWriter typeWriter)
        {
            if (typeWriter == null)
            {
                throw new ArgumentNullException("typeWriter");
            }

            if (value == null)
            {
                // Zero means a null object
                Write7BitEncodedInt(0);
            }
            else
            {
                var index = typeWriterMap[typeWriter.GetType()];
                // Because zero means null object, we add one to the index before writing it to the file
                Write7BitEncodedInt(index + 1);
                typeWriter.Write(this, value);
            }
        }
예제 #6
0
        /// <summary>
        /// Retrieves the worker writer for the specified type.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <returns>The worker writer.</returns>
        /// <remarks>This should be called from the ContentTypeWriter.Initialize method.</remarks>
        public ContentTypeWriter GetTypeWriter(Type type)
        {
            ContentTypeWriter result   = null;
            var  contentTypeWriterType = typeof(ContentTypeWriter <>).MakeGenericType(type);
            Type typeWriterType;

            if (typeWriterMap.TryGetValue(contentTypeWriterType, out typeWriterType))
            {
                result = (ContentTypeWriter)Activator.CreateInstance(typeWriterType);
            }
            else if (type.IsArray)
            {
                if (type.GetArrayRank() != 1)
                {
                    throw new NotSupportedException("We don't support multidimensional arrays!");
                }

                result = (ContentTypeWriter)Activator.CreateInstance(typeof(ArrayWriter <>).MakeGenericType(type.GetElementType()));
                typeWriterMap.Add(contentTypeWriterType, result.GetType());
            }
            else if (type.IsEnum)
            {
                result = (ContentTypeWriter)Activator.CreateInstance(typeof(EnumWriter <>).MakeGenericType(type));
                typeWriterMap.Add(contentTypeWriterType, result.GetType());
            }
            else if (type.IsGenericType)
            {
                var inputTypeDef = type.GetGenericTypeDefinition();

                Type chosen = null;
                foreach (var kvp in typeWriterMap)
                {
                    var args = kvp.Key.GetGenericArguments();

                    if (args.Length == 0)
                    {
                        continue;
                    }

                    if (!args[0].IsGenericType)
                    {
                        continue;
                    }

                    // Compare generic type definition
                    var keyTypeDef = args[0].GetGenericTypeDefinition();
                    if (inputTypeDef == keyTypeDef)
                    {
                        chosen = kvp.Value;
                        break;
                    }
                }

                try
                {
                    var concreteType = type.GetGenericArguments();
                    result = (ContentTypeWriter)Activator.CreateInstance(chosen.MakeGenericType(concreteType));

                    // save it for next time.
                    typeWriterMap.Add(contentTypeWriterType, result.GetType());
                }
                catch (Exception)
                {
                    throw new InvalidContentException(String.Format("Could not find ContentTypeWriter for type '{0}'", type.Name));
                }
            }
            else
            {
                result = (ContentTypeWriter)Activator.CreateInstance(typeof(ReflectiveWriter <>).MakeGenericType(type));
                typeWriterMap.Add(contentTypeWriterType, result.GetType());
            }


            var initMethod = result.GetType().GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance);

            initMethod.Invoke(result, new object[] { this });

            return(result);
        }