public static XStorageObjectBase CreateXStorageObject(XmlElement xmlObject, XTypeInfo typeInfo) { XStorageObjectBase xobj; Guid oid = new Guid(xmlObject.GetAttribute("oid")); Int64 nTS; if (xmlObject.HasAttribute("ts")) { nTS = Int32.Parse(xmlObject.GetAttribute("ts")); } else { nTS = -1; } bool bIsNew = false; if (xmlObject.HasAttribute("delete")) { xobj = new XStorageObjectToDelete(typeInfo, oid, nTS, true); } else { bIsNew = xmlObject.HasAttribute("new"); xobj = new XStorageObjectToSave(typeInfo, oid, nTS, bIsNew); } bool bNeedTrackUniqueIndexParticipation = typeInfo.HasUniqueIndexes && typeInfo.DeferrableIndexes && xobj is XStorageObjectToSave; // по всем свойствам без признака loaded="0" foreach (XmlElement xmlProp in xmlObject.SelectNodes("*[not(@loaded)]")) { XPropInfoBase xprop = typeInfo.GetProp(xmlProp.LocalName); if (xprop == null) { continue; } // если на xml-свойстве неудаляемого объекта есть атрибут с идентификатором цепочки кусочных данных, то занесем его в специальный словарь if (xobj is XStorageObjectToSave && xmlProp.HasAttribute(ATTR_CHUNCK_CHAIN_ID)) { ((XStorageObjectToSave)xobj).PropertiesWithChunkedData.Add(xprop.Name, new Guid(xmlProp.GetAttribute(ATTR_CHUNCK_CHAIN_ID))); } // членство в массиве проигнорируем if (xprop is XPropInfoObjectArray) { if (((XPropInfoObjectArray)xprop).Capacity == XPropCapacity.ArrayMembership) { continue; } } // пустые массивные свойства новых объектов проигнорируем if (bIsNew) { if (xprop is XPropInfoObjectArray || xprop is XPropInfoObjectLink) { if (!xmlProp.HasChildNodes) { continue; } } } xobj.Props.Add(xprop.Name, getPropValue(xmlProp, xprop)); // если свойство участвует в уникальном индексе, запомним это if (bNeedTrackUniqueIndexParticipation) { if (typeInfo.IsPropIncludedIntoUniqueIndex(xprop.Name)) { ((XStorageObjectToSave)xobj).ParticipateInUniqueIndex = true; } } } return(xobj); }