/// <summary>
        /// Writes the JSON representation of the object.
        /// </summary>
        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="value">The value.</param>
        /// <param name="serializer">The calling serializer.</param>
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;

            Type t = value.GetType();

            object result   = FSharpUtils.GetUnionFields(null, value, t, null);
            object info     = FSharpUtils.GetUnionCaseInfo(result);
            object fields   = FSharpUtils.GetUnionCaseFields(result);
            object caseName = FSharpUtils.GetUnionCaseInfoName(info);

            object[] fieldsAsArray = fields as object[];

            writer.WriteStartObject();
            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName);
            writer.WriteValue((string)caseName);
            if (fieldsAsArray != null && fieldsAsArray.Length > 0)
            {
                writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName);
                serializer.Serialize(writer, fields);
            }
            writer.WriteEndObject();
        }
        private static Union CreateUnion(Type t)
        {
            Union u = new Union();

            u.TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null);
            u.Cases     = new List <UnionCase>();

            object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null);

            foreach (object unionCaseInfo in cases)
            {
                UnionCase unionCase = new UnionCase();
                unionCase.Tag         = (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo);
                unionCase.Name        = (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo);
                unionCase.Fields      = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo);
                unionCase.FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null);
                unionCase.Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null);

                u.Cases.Add(unionCase);
            }

            return(u);
        }
Esempio n. 3
0
 private static DiscriminatedUnionConverter.Union CreateUnion(Type t)
 {
     DiscriminatedUnionConverter.Union union = new DiscriminatedUnionConverter.Union()
     {
         TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, new object[] { t, null }),
         Cases     = new List <DiscriminatedUnionConverter.UnionCase>()
     };
     object[] getUnionCases = (object[])FSharpUtils.GetUnionCases(null, new object[] { t, null });
     for (int i = 0; i < (int)getUnionCases.Length; i++)
     {
         object obj = getUnionCases[i];
         DiscriminatedUnionConverter.UnionCase unionCase = new DiscriminatedUnionConverter.UnionCase()
         {
             Tag         = (int)FSharpUtils.GetUnionCaseInfoTag(obj),
             Name        = (string)FSharpUtils.GetUnionCaseInfoName(obj),
             Fields      = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(obj, new object[0]),
             FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, new object[] { obj, null }),
             Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, new object[] { obj, null })
         };
         union.Cases.Add(unionCase);
     }
     return(union);
 }
Esempio n. 4
0
        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value of object being read.</param>
        /// <param name="serializer">The calling serializer.</param>
        /// <returns>The object value.</returns>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return(null);
            }

            object matchingCaseInfo = null;
            string caseName         = null;
            JArray fields           = null;

            // start object
            ReadAndAssert(reader);

            while (reader.TokenType == JsonToken.PropertyName)
            {
                string propertyName = reader.Value.ToString();
                if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase))
                {
                    ReadAndAssert(reader);

                    IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null);

                    caseName = reader.Value.ToString();

                    foreach (object c in cases)
                    {
                        if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName)
                        {
                            matchingCaseInfo = c;
                            break;
                        }
                    }

                    if (matchingCaseInfo == null)
                    {
                        throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
                    }
                }
                else if (string.Equals(propertyName, FieldsPropertyName, StringComparison.OrdinalIgnoreCase))
                {
                    ReadAndAssert(reader);
                    if (reader.TokenType != JsonToken.StartArray)
                    {
                        throw JsonSerializationException.Create(reader, "Union fields must been an array.");
                    }

                    fields = (JArray)JToken.ReadFrom(reader);
                }
                else
                {
                    throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, propertyName));
                }

                ReadAndAssert(reader);
            }

            if (matchingCaseInfo == null)
            {
                throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName));
            }
            if (fields == null)
            {
                throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, FieldsPropertyName));
            }

            PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo);

            if (fieldProperties.Length != fields.Count)
            {
                throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties definied by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
            }

            object[] typedFieldValues = new object[fieldProperties.Length];
            for (int i = 0; i < fields.Count; i++)
            {
                JToken       t             = fields[i];
                PropertyInfo fieldProperty = fieldProperties[i];

                typedFieldValues[i] = t.ToObject(fieldProperty.PropertyType);
            }

            return(FSharpUtils.MakeUnion(null, matchingCaseInfo, typedFieldValues, null));
        }