private static MeshModelMetadata ReadFrom(Stream stream, IGuidGenerator fallbackGuidGenerator)
        {
            // Needed for later property validation
            var hasGuid      = false;
            var hasName      = false;
            var hasPartCount = false;

            var settings = new XmlReaderSettings
            {
                IgnoreComments               = true,
                IgnoreWhitespace             = true,
                IgnoreProcessingInstructions = true,
                CloseInput = false,
                NameTable  = new NameTable()
            };

            using (var reader = XmlReader.Create(stream, settings))
            {
                var result = new MeshModelMetadata();
                reader.MoveToElement();
                while (reader.Read())
                {
                    switch (reader.Name)
                    {
                    case "Guid":
                        result.Guid = Guid.ParseExact(reader.ReadString(), "N");
                        hasGuid     = true;
                        break;

                    case "TriangulationHash":
                        result.TriangulationHash = Guid.ParseExact(reader.ReadString(), "N");
                        break;

                    case "Name":
                        result.Name = reader.ReadString();
                        hasName     = true;
                        break;

                    case "PartCount":
                        result.PartCount = int.Parse(reader.ReadString(), System.Globalization.CultureInfo.InvariantCulture);
                        hasPartCount     = true;
                        break;

                    case "FileVersion":
                        result.FileVersion = new Version(reader.ReadString());
                        break;

                    case "SourceFormat":
                        result.SourceFormat = reader.ReadString();
                        break;

                    case "Layer":
                        var layer = new List <string>();
                        while (reader.Read() && reader.NodeType != XmlNodeType.EndElement)
                        {
                            layer.Add(reader.ReadString());
                        }
                        result.Layer = layer.ToArray();
                        break;

                    case "SourceModels":
                        var sourceModels = new List <string>();
                        while (reader.Read() && reader.NodeType != XmlNodeType.EndElement)
                        {
                            sourceModels.Add(reader.ReadString());
                        }
                        result.SourceModels = sourceModels.ToArray();
                        break;

                    case "MeshValueEntries":
                        var entries = new List <MeshValueEntry>();
                        while (reader.Read() && reader.NodeType != XmlNodeType.EndElement)
                        {
                            if (reader.Name == "MeshValueEntry")
                            {
                                entries.Add(MeshValueEntry.Read(reader));
                            }
                        }
                        result.MeshValueEntries = entries.ToArray();
                        break;
                    }
                }

                // validation for mendatory properties since version 5.1.0.0 and missing Guid fallback for older versions
                if (result.FileVersion != null && result.FileVersion >= new Version(5, 1, 0, 0))
                {
                    if (!hasGuid)
                    {
                        throw new InvalidOperationException(MeshModelHelper.FormatResource <MeshModel>("InvalidFormatMissingProperty_ErrorText", "Guid"));
                    }

                    if (!hasName)
                    {
                        throw new InvalidOperationException(MeshModelHelper.FormatResource <MeshModel>("InvalidFormatMissingProperty_ErrorText", "Name"));
                    }

                    if (!hasPartCount)
                    {
                        throw new InvalidOperationException(MeshModelHelper.FormatResource <MeshModel>("InvalidFormatMissingProperty_ErrorText", "PartCount"));
                    }
                }
                else
                {
                    if (!hasGuid)
                    {
                        result.Guid = fallbackGuidGenerator.CreateGuid();
                    }
                }

                return(result);
            }
        }