private Property deserialize(PropertyArt propertyArt, Type expectedType)
        {
            // Establish the property name
            string propertyName = _reader.GetAttributeAsString(Attributes.Name);

            // Establish the property type
            Type propertyType = _reader.GetAttributeAsType(Attributes.Type);

            // id propertyType is not defined, we'll take the expectedType)
            if (propertyType == null)
            {
                propertyType = expectedType;
            }

            // create the property from the tag
            Property property = Property.CreateInstance(propertyArt, propertyName, propertyType);

            // Null property?
            var nullProperty = property as NullProperty;

            if (nullProperty != null)
            {
                return(nullProperty);
            }

            // is it simple property?
            var simpleProperty = property as SimpleProperty;

            if (simpleProperty != null)
            {
                parseSimpleProperty(_reader, simpleProperty);
                return(simpleProperty);
            }

            // This is not a null property and not a simple property
            // it could be only ReferenceProperty or a reference

            int referenceId = _reader.GetAttributeAsInt(Attributes.ReferenceId);

            // Adding property to cache, it must be done before deserializing the object.
            // Otherwise stack overflow occures if the object references itself
            var referenceTarget = property as ReferenceTargetProperty;

            if (referenceTarget != null && referenceId > 0)
            {
                referenceTarget.Reference = new ReferenceInfo()
                {
                    Id = referenceId, IsProcessed = true
                };
                _propertyCache.Add(referenceId, referenceTarget);
            }

            if (property == null)
            {
                // Property was not created yet, it can be created as a reference from its id
                if (referenceId < 1)
                {
                    // there is no reference, so the property cannot be restored
                    return(null);
                }

                property = createProperty(referenceId, propertyName, propertyType);
                if (property == null)
                {
                    // Reference was not created
                    return(null);
                }

                // property was successfully restored as a reference
                return(property);
            }

            var multiDimensionalArrayProperty = property as MultiDimensionalArrayProperty;

            if (multiDimensionalArrayProperty != null)
            {
                parseMultiDimensionalArrayProperty(multiDimensionalArrayProperty);
                return(multiDimensionalArrayProperty);
            }

            var singleDimensionalArrayProperty = property as SingleDimensionalArrayProperty;

            if (singleDimensionalArrayProperty != null)
            {
                parseSingleDimensionalArrayProperty(singleDimensionalArrayProperty);
                return(singleDimensionalArrayProperty);
            }

            var dictionaryProperty = property as DictionaryProperty;

            if (dictionaryProperty != null)
            {
                parseDictionaryProperty(dictionaryProperty);
                return(dictionaryProperty);
            }

            var collectionProperty = property as CollectionProperty;

            if (collectionProperty != null)
            {
                parseCollectionProperty(collectionProperty);
                return(collectionProperty);
            }

            var complexProperty = property as ComplexProperty;

            if (complexProperty != null)
            {
                parseComplexProperty(complexProperty);
                return(complexProperty);
            }

            return(property);
        }