/// <summary> /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <returns>NullProperty if the value is null</returns> public Property CreateProperty(string name, object value) { if (value == null) { return(new NullProperty(name)); } // If value type is recognized, it will be taken from typeinfo cache var typeInfo = InternalTypeInfo.GetTypeInfo(value); // Is it simple type var property = CreateSimpleProperty(name, typeInfo, value); if (property != null) { return(property); } // From now it can only be an instance of ReferenceTargetProperty var referenceTarget = CreateReferenceTargetInstance(name, typeInfo); // Search in Cache ReferenceTargetProperty cachedTarget; if (_propertyCache.TryGetValue(value, out cachedTarget)) { // Value was already referenced // Its reference will be used cachedTarget.Reference.Count++; referenceTarget.MakeFlatCopyFrom(cachedTarget); return(referenceTarget); } // Target was not found in cache // it must be created // Adding property to cache referenceTarget.Reference = new ReferenceInfo { Id = _currentReferenceId++ }; _propertyCache.Add(value, referenceTarget); // Parsing the property var handled = FillSingleDimensionalArrayProperty(referenceTarget as SingleDimensionalArrayProperty, typeInfo, value); handled = handled || FillMultiDimensionalArrayProperty(referenceTarget as MultiDimensionalArrayProperty, typeInfo, value); handled = handled || FillDictionaryProperty(referenceTarget as DictionaryProperty, typeInfo, value); handled = handled || FillCollectionProperty(referenceTarget as CollectionProperty, typeInfo, value); handled = handled || FillComplexProperty(referenceTarget as ComplexProperty, typeInfo, value); if (!handled) { throw new InvalidOperationException($"Property cannot be filled. Property: {referenceTarget}"); } return(referenceTarget); }