/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }