How to write a comment to an XML file when using the XmlSerializer?

后端 未结 5 643
刺人心
刺人心 2020-12-01 06:25

I have an object Foo which I serialize to an XML stream.

public class Foo {
  // The application version, NOT the file version!
  public string Version {get         


        
5条回答
  •  臣服心动
    2020-12-01 07:23

    Probably late to the party but I had problems when I was trying to deserialize using Kirill Polishchuk solution. Finally I decided to edit the XML after serializing it and the solution looks like:

    public static void WriteXml(object objectToSerialize, string path)
    {
        try
        {
            using (var w = new XmlTextWriter(path, null))
            {
                w.Formatting = Formatting.Indented;
                var serializer = new XmlSerializer(objectToSerialize.GetType());
                serializer.Serialize(w, objectToSerialize);
            }
    
            WriteComments(objectToSerialize, path);
        }
        catch (Exception e)
        {
            throw new Exception($"Could not save xml to path {path}. Details: {e}");
        }
    }
    
    public static T ReadXml(string path) where T:class, new()
    {
        if (!File.Exists(path))
            return null;
        try
        {
            using (TextReader r = new StreamReader(path))
            {
                var deserializer = new XmlSerializer(typeof(T));
                var structure = (T)deserializer.Deserialize(r);
                return structure;
            }
        }
        catch (Exception e)
        {
            throw new Exception($"Could not open and read file from path {path}. Details: {e}");
        }
    }
    
    private static void WriteComments(object objectToSerialize, string path)
    {
        try
        {
            var propertyComments = GetPropertiesAndComments(objectToSerialize);
            if (!propertyComments.Any()) return;
    
            var doc = new XmlDocument();
            doc.Load(path);
    
            var parent = doc.SelectSingleNode(objectToSerialize.GetType().Name);
            if (parent == null) return;
    
            var childNodes = parent.ChildNodes.Cast().Where(n => propertyComments.ContainsKey(n.Name));
            foreach (var child in childNodes)
            {
                parent.InsertBefore(doc.CreateComment(propertyComments[child.Name]), child);
            }
    
            doc.Save(path);
        }
        catch (Exception)
        {
            // ignored
        }
    }
    
    private static Dictionary GetPropertiesAndComments(object objectToSerialize)
    {
        var propertyComments = objectToSerialize.GetType().GetProperties()
            .Where(p => p.GetCustomAttributes(typeof(XmlCommentAttribute), false).Any())
            .Select(v => new
            {
                v.Name,
                ((XmlCommentAttribute) v.GetCustomAttributes(typeof(XmlCommentAttribute), false)[0]).Value
            })
            .ToDictionary(t => t.Name, t => t.Value);
        return propertyComments;
    }
    
    [AttributeUsage(AttributeTargets.Property)]
    public class XmlCommentAttribute : Attribute
    {
        public string Value { get; set; }
    }
    

提交回复
热议问题