// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.IO; using System.Net.Http.Formatting; using System.Threading.Tasks; namespace System.Net.Http { /// /// Contains a value as well as an associated that will be /// used to serialize the value when writing this content. /// public class ObjectContent : HttpContent { private object _value; private readonly MediaTypeFormatter _formatter; /// /// Initializes a new instance of the class. /// /// The type of object this instance will contain. /// The value of the object this instance will contain. /// The formatter to use when serializing the value. public ObjectContent(Type type, object value, MediaTypeFormatter formatter) : this(type, value, formatter, null) { } /// /// Initializes a new instance of the class. /// /// The type of object this instance will contain. /// The value of the object this instance will contain. /// The formatter to use when serializing the value. /// The media type to associate with this object. public ObjectContent(Type type, object value, MediaTypeFormatter formatter, string mediaType) { if (type == null) { throw new ArgumentNullException("type"); } if (formatter == null) { throw new ArgumentNullException("formatter"); } _formatter = formatter; ObjectType = type; VerifyAndSetObject(value); _formatter.SetDefaultContentHeaders(type, Headers, mediaType); } /// /// Gets the type of object managed by this instance. /// public Type ObjectType { get; private set; } /// /// The formatter associated with this content instance. /// public MediaTypeFormatter Formatter { get { return _formatter; } } /// /// Gets or sets the value of the current . /// public object Value { get { return _value; } set { VerifyAndSetObject(value); } } /// /// Asynchronously serializes the object's content to the given . /// /// The to which to write. /// The associated . /// A instance that is asynchronously serializing the object's content. protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { return _formatter.WriteToStreamAsync(ObjectType, Value, stream, Headers, context); } /// /// Computes the length of the stream if possible. /// /// The computed length of the stream. /// true if the length has been computed; otherwise false. protected override bool TryComputeLength(out long length) { length = -1; return false; } private static bool IsTypeNullable(Type type) { return !type.IsValueType || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)); } private void VerifyAndSetObject(object value) { Contract.Assert(ObjectType != null, "Type cannot be null"); if (value == null) { // Null may not be assigned to value types (unless Nullable) if (!IsTypeNullable(ObjectType)) { throw new InvalidOperationException(RS.Format(Properties.Resources.CannotUseNullValueType, typeof(ObjectContent).Name, ObjectType.Name)); } } else { // Non-null objects must be a type assignable to Type Type objectType = value.GetType(); if (!ObjectType.IsAssignableFrom(objectType)) { throw new ArgumentException(RS.Format(Properties.Resources.ObjectAndTypeDisagree, objectType.Name, ObjectType.Name), "value"); } if (!_formatter.CanWriteType(objectType)) { throw new InvalidOperationException(RS.Format(Properties.Resources.ObjectContent_FormatterCannotWriteType, _formatter.GetType().FullName, objectType.Name)); } } _value = value; } } /// /// Generic form of . /// /// The type of object this class will contain. [SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "Class contains generic forms")] public class ObjectContent : ObjectContent { /// /// Initializes a new instance of the class. /// /// The value of the object this instance will contain. /// The formatter to use when serializing the value. public ObjectContent(T value, MediaTypeFormatter formatter) : this(value, formatter, null) { } /// /// Initializes a new instance of the class. /// /// The value of the object this instance will contain. /// The formatter to use when serializing the value. /// The media type to associate with this object. public ObjectContent(T value, MediaTypeFormatter formatter, string mediaType) : base(typeof(T), value, formatter, mediaType) { } } }