object CreateValueInternal( BitStreamReader reader, IContract contract, DsdlProperty member, ContainerContract containerContract, DsdlProperty containerMember, object existingValue, DsdlType scheme, Type objectType, bool tailArrayOptimization = false) { switch (scheme) { case VoidDsdlType t: ReadAlignment(reader, t); return(null); case PrimitiveDsdlType t: var primitive = ReadPrimitiveType(reader, t); return(EnsureType(reader, primitive, CultureInfo.InvariantCulture, contract, objectType)); case ArrayDsdlType t when t.IsStringLike && contract.UnderlyingType == typeof(string): var list = CreateList(reader, StringContract, member, null, t, tailArrayOptimization) as IEnumerable <byte>; return(_encoding.GetString(list.ToArray())); case ArrayDsdlType t: return(CreateList(reader, contract, member, existingValue, t, tailArrayOptimization)); case CompositeDsdlTypeBase t: return(CreateObject(reader, contract, member, containerContract, containerMember, existingValue, objectType, t, tailArrayOptimization)); default: throw new ArgumentOutOfRangeException(nameof(scheme)); } }
bool CalculatePropertyValues(object value, ContainerContract contract, DsdlProperty property, out IContract memberContract, out object memberValue) { memberContract = null; memberValue = null; if (property.Ignored || !property.Readable) { return(false); } memberValue = property.ValueProvider.GetValue(value); if (memberValue == null) { return(false); } if (property.PropertyContract == null) { property.PropertyContract = _serializer.ContractResolver.ResolveContract(property.PropertyType); } memberContract = (property.PropertyContract.IsSealed) ? property.PropertyContract : _serializer.ContractResolver.ResolveContract(memberValue.GetType()); if (!CheckForCircularReference(memberValue, property, memberContract)) { return(false); } if (!CheckDsdlTypeCompatibility(property.DsdlType, memberContract)) { throw new InvalidOperationException( $"DSDL type mismatch for property '{contract.UnderlyingType.FullName}.{property.UnderlyingName}'."); } return(true); }
bool SetPropertyValue( DsdlProperty property, ContainerContract containerContract, DsdlProperty containerProperty, BitStreamReader reader, object target, DsdlType scheme, bool tailArrayOptimization) { if (property.Ignored) { return(true); } if (property.PropertyContract == null) { property.PropertyContract = GetContractSafe(property.PropertyType); } bool useExistingValue = false; object currentValue = null; if (property.Readable) { currentValue = property.ValueProvider.GetValue(target); } IContract propertyContract; if (currentValue == null) { propertyContract = property.PropertyContract; } else { propertyContract = GetContractSafe(currentValue.GetType()); useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType()); } var value = CreateValueInternal( reader, propertyContract, property, containerContract, containerProperty, (useExistingValue) ? currentValue : null, scheme, property.PropertyType, tailArrayOptimization); // always set the value if useExistingValue is false, // otherwise also set it if CreateValue returns a new value compared to the currentValue // this could happen because of a JsonConverter against the type if ((!useExistingValue || value != currentValue) && ShouldSetPropertyValue(property, containerContract as ObjectContract, value)) { property.ValueProvider.SetValue(target, value); return(true); } // the value wasn't set be JSON was populated onto the existing value return(useExistingValue); }
object CreateObject( BitStreamReader reader, IContract contract, DsdlProperty member, ContainerContract containerContract, DsdlProperty containerMember, object existingValue, Type objectType, CompositeDsdlTypeBase scheme, bool tailArrayOptimization) { if (HasNoDefinedType(contract)) { return(CreateUnknownObject(reader, scheme)); } switch (contract) { case ObjectContract objectContract: { bool createdFromNonDefaultCreator = false; object targetObject; // check that if type name handling is being used that the existing value is compatible with the specified type if (existingValue != null && objectType != null && objectType.IsAssignableFrom(existingValue.GetType())) { targetObject = existingValue; } else { targetObject = CreateNewObject(reader, objectContract, member, containerMember, out createdFromNonDefaultCreator); } // don't populate if read from non-default creator because the object has already been read if (createdFromNonDefaultCreator) { return(targetObject); } return(PopulateObject(targetObject, reader, objectContract, member, scheme, tailArrayOptimization)); } case DictionaryContract dictionaryContract: { object targetDictionary; if (existingValue == null) { var dictionary = CreateNewDictionary(reader, dictionaryContract, out bool createdFromNonDefaultCreator); if (createdFromNonDefaultCreator && !dictionaryContract.HasParameterizedCreatorInternal) { throw new SerializationException("Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } PopulateDictionary(dictionary, reader, dictionaryContract, member, scheme, tailArrayOptimization); if (createdFromNonDefaultCreator) { ObjectConstructor <object> creator = dictionaryContract.OverrideCreator ?? dictionaryContract.ParameterizedCreator; return(creator(dictionary)); } else if (dictionary is IWrappedDictionary wrappedDictionary) { return(wrappedDictionary.UnderlyingDictionary); } targetDictionary = dictionary; } else { targetDictionary = PopulateDictionary( dictionaryContract.ShouldCreateWrapper || !(existingValue is IDictionary) ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary)existingValue, reader, dictionaryContract, member, scheme, tailArrayOptimization); } return(targetDictionary); } } throw new SerializationException($"Cannot deserialize the current object."); }
void SerializeObjectCore( BitStreamWriter writer, Func <string, ResolvedProperty?> propertyResolver, ContainerContract containerContract, DsdlType derivedDsdlType, bool tailArrayOptimization) { var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(containerContract, derivedDsdlType); //WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); VoidDsdlType voidDsdlType = null; int voidDsdlTypeIndex = -1; var isUnion = dsdlScheme.IsUnion; var unionMemberFound = false; for (int i = 0; i < dsdlScheme.Fields.Count; i++) { var dsdlMember = dsdlScheme.Fields[i]; var isLastMember = i == dsdlScheme.Fields.Count - 1; if ((voidDsdlType = (dsdlMember.Type as VoidDsdlType)) != null) { voidDsdlTypeIndex = i; if (!isUnion) { WriteAlignment(writer, voidDsdlType); } continue; } var resolvedProp = propertyResolver(dsdlMember.Name); if (isUnion) { if (resolvedProp == null) { continue; } if (unionMemberFound) { throw new InvalidOperationException($"Cannot find single union value for type '{containerContract.UnderlyingType.FullName}'."); } unionMemberFound = true; WriteUnionFieldIndex(writer, i, dsdlScheme); var rp = resolvedProp.Value; SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type); } else { if (resolvedProp == null) { throw new InvalidOperationException($"Cannot resove member '{containerContract.UnderlyingType.FullName}.{dsdlMember.Name}'."); } var rp = resolvedProp.Value; var tao = tailArrayOptimization && isLastMember && dsdlMember.Type is ArrayDsdlType adt; SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type, tao); } } if (isUnion && !unionMemberFound) { if (voidDsdlType != null) { WriteUnionFieldIndex(writer, voidDsdlTypeIndex, dsdlScheme); WriteAlignment(writer, voidDsdlType); } else { throw new InvalidOperationException($"Cannot find union value for '{containerContract.UnderlyingType.FullName}' type."); } } }