示例#1
0
        /// <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
            if (_propertyCache.TryGetValue(value, out var 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);
        }
示例#2
0
        private bool FillComplexProperty(ComplexProperty property, InternalTypeInfo typeInfo, object value)
        {
            if (property == null)
            {
                return(false);
            }

            // Parsing properties
            ParseProperties(property, typeInfo, value);

            return(true);
        }
示例#3
0
        private static Property CreateSimpleProperty(string name, InternalTypeInfo typeInfo, object value)
        {
            if (!typeInfo.IsSimple)
            {
                return(null);
            }
            var result = new SimpleProperty(name, typeInfo.Type)
            {
                Value = value
            };

            return(result);
        }
示例#4
0
        private void ParseCollectionItems(CollectionProperty property, InternalTypeInfo info, object value)
        {
            property.ElementType = info.ElementType;

            var collection = (IEnumerable)value;

            foreach (var item in collection)
            {
                var itemProperty = CreateProperty(null, item);

                property.Items.Add(itemProperty);
            }
        }
示例#5
0
        private void ParseProperties(ComplexProperty property, InternalTypeInfo typeInfo, object value)
        {
            var propertyInfos = _propertyProvider.GetProperties(typeInfo);

            foreach (var propertyInfo in propertyInfos)
            {
                var subValue = propertyInfo.GetValue(value, _emptyObjectArray);

                var subProperty = CreateProperty(propertyInfo.Name, subValue);

                property.Properties.Add(subProperty);
            }
        }
示例#6
0
        private bool FillDictionaryProperty(DictionaryProperty property, InternalTypeInfo info, object value)
        {
            if (property == null)
            {
                return(false);
            }

            // Properties
            ParseProperties(property, info, value);

            // Items
            ParseDictionaryItems(property, info, value);

            return(true);
        }
示例#7
0
        private bool FillCollectionProperty(CollectionProperty property, InternalTypeInfo info, object value)
        {
            if (property == null)
            {
                return(false);
            }

            // Parsing properties
            ParseProperties(property, info, value);

            // Parse Items
            ParseCollectionItems(property, info, value);

            return(true);
        }
示例#8
0
        private void ParseDictionaryItems(DictionaryProperty property, InternalTypeInfo info, object value)
        {
            property.KeyType   = info.KeyType;
            property.ValueType = info.ElementType;

            var dictionary = (IDictionary)value;

            foreach (DictionaryEntry entry in dictionary)
            {
                var keyProperty = CreateProperty(null, entry.Key);

                var valueProperty = CreateProperty(null, entry.Value);

                property.Items.Add(new KeyValueItem(keyProperty, valueProperty));
            }
        }
        /// <summary>
        ///     Fills the <see cref="InternalTypeInfo.KeyType" /> and <see cref="InternalTypeInfo.ElementType" /> properties
        ///     to target <see paramref="target" /> from <paramref name="source" />.
        /// </summary>
        /// <returns><c>TRUE</c> if the key and value definition was found, otherwise <c>FALSE</c></returns>
        private static bool FillKeyAndElementType(InternalTypeInfo source, Type target)
        {
            var targetInfo = target.GetTypeInfo();

            if (!targetInfo.IsGenericType)
            {
                return(false);
            }
            var arguments = target.GetGenericArguments();

            if (source.IsDictionary)
            {
                // in Dictionary there are keys and values
                source.KeyType     = arguments[0];
                source.ElementType = arguments[1];
            }
            else
            {
                // In Collection there are only items
                source.ElementType = arguments[0];
            }

            return(arguments.Length > 0);
        }
        /// <summary>
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static InternalTypeInfo GetTypeInfo(Type type)
        {
            // check if Info is in cache
            var typeInfo = Cache.TryGetTypeInfo(type);

            if (typeInfo != null)
            {
                return(typeInfo);
            }
            // no info in cache yet
            typeInfo = new InternalTypeInfo
            {
                Type     = type,
                IsSimple = Tools.IsSimple(type)
            };

            // check if array of byte
            if (type == typeof(byte[]))
            {
                typeInfo.ElementType = typeof(byte);
            }

            // Only not simple types can be Collections
            if (!typeInfo.IsSimple)
            {
                // check if it is an Array
                typeInfo.IsArray = Tools.IsArray(type);

                if (typeInfo.IsArray)
                {
                    // Array? What is its element type?
                    if (type.HasElementType)
                    {
                        typeInfo.ElementType = type.GetElementType();
                    }

                    // How many dimensions
                    typeInfo.ArrayDimensionCount = type.GetArrayRank();
                }
                else
                {
                    // It is not Array, maybe Enumerable?
                    typeInfo.IsEnumerable = Tools.IsEnumerable(type);
                    if (typeInfo.IsEnumerable)
                    {
                        // it is Enumerable maybe Collection?
                        typeInfo.IsCollection = Tools.IsCollection(type);

                        if (typeInfo.IsCollection)
                        {
                            // Sure it is a Collection, but maybe Dictionary also?
                            typeInfo.IsDictionary = Tools.IsDictionary(type);

                            // Fill its key and value types, if the listing is generic
                            bool elementTypeDefinitionFound;
                            var  examinedType = type;
                            do
                            {
                                elementTypeDefinitionFound = FillKeyAndElementType(typeInfo, examinedType);
                                examinedType = examinedType.GetTypeInfo().BaseType;
                                // until key and element definition was found, or the base typ is an object
                            } while (!elementTypeDefinitionFound && examinedType != null &&
                                     examinedType != typeof(object));
                        }
                    }
                }
            }

            if (!Cache.Contains(typeInfo))
            {
                Cache.Add(typeInfo);
            }

            return(typeInfo);
        }
示例#11
0
        private static ReferenceTargetProperty CreateReferenceTargetInstance(string name, InternalTypeInfo typeInfo)
        {
            // Is it array?
            if (typeInfo.IsArray)
            {
                if (typeInfo.ArrayDimensionCount < 2)
                {
                    return(new SingleDimensionalArrayProperty(name, typeInfo.Type));
                }
                // MultiD-Array
                return(new MultiDimensionalArrayProperty(name, typeInfo.Type));
            }

            if (typeInfo.IsDictionary)
            {
                return(new DictionaryProperty(name, typeInfo.Type));
            }
            if (typeInfo.IsCollection)
            {
                return(new CollectionProperty(name, typeInfo.Type));
            }
            if (typeInfo.IsEnumerable)
            {
                return(new CollectionProperty(name, typeInfo.Type));
            }

            // If nothing was recognized, a complex type will be created
            return(new ComplexProperty(name, typeInfo.Type));
        }
示例#12
0
        private bool FillSingleDimensionalArrayProperty(SingleDimensionalArrayProperty property, InternalTypeInfo info,
                                                        object value)
        {
            if (property == null)
            {
                return(false);
            }

            property.ElementType = info.ElementType;

            var analyzer = new ArrayAnalyzer(value);

            // Dimensionen
            var dimensionInfo = analyzer.ArrayInfo.DimensionInfos[0];

            property.LowerBound = dimensionInfo.LowerBound;

            // Items
            foreach (var item in analyzer.GetValues())
            {
                var itemProperty = CreateProperty(null, item);

                property.Items.Add(itemProperty);
            }

            return(true);
        }
示例#13
0
        private bool FillMultiDimensionalArrayProperty(MultiDimensionalArrayProperty property, InternalTypeInfo info,
                                                       object value)
        {
            if (property == null)
            {
                return(false);
            }
            property.ElementType = info.ElementType;

            var analyzer = new ArrayAnalyzer(value);

            // DimensionInfos
            property.DimensionInfos = analyzer.ArrayInfo.DimensionInfos;

            // Items
            foreach (var indexSet in analyzer.GetIndexes())
            {
                var subValue     = ((Array)value).GetValue(indexSet);
                var itemProperty = CreateProperty(null, subValue);

                property.Items.Add(new MultiDimensionalArrayItem(indexSet, itemProperty));
            }

            return(true);
        }