How to add XmlInclude attribute dynamically

后端 未结 4 1687
青春惊慌失措
青春惊慌失措 2020-11-27 05:20

I have the following classes

[XmlRoot]
public class AList
{
   public List ListOfBs {get; set;}
}

public class B
{
   public string BaseProperty {g         


        
相关标签:
4条回答
  • 2020-11-27 05:29

    Have a look at the documentation of XmlSerializer. There is a constructor which expects known types as the second parameter. That should work fine for you use case.

    0 讨论(0)
  • 2020-11-27 05:30

    Building on Marc's first answer (I only have to read, so I don't need to prevent the weird output), I use a more dynamic/generic type-array to account for unknown types, inspired by this codeproject.

        public static XmlSerializer GetSerializer()
        {
            var lListOfBs = (from lAssembly in AppDomain.CurrentDomain.GetAssemblies()
                               from lType in lAssembly.GetTypes()
                               where typeof(B).IsAssignableFrom(lType)
                               select lType).ToArray();
            return new XmlSerializer(typeof(AList), lListOfBs);
        }
    

    (One could probably make it more efficient, e.g. using a static or read-only type-array in stead of a local variable. That would avoid repeatedly using Reflection. But I don't know enough about when assemblies get loaded and classes and properties get initialized, to know if that would get you into trouble. My usage is not that much, to take the time to investigate this all, so I just use the same Reflection multiple times.)

    0 讨论(0)
  • 2020-11-27 05:40

    Two options; the simplest (but giving odd xml) is:

    XmlSerializer ser = new XmlSerializer(typeof(AList),
        new Type[] {typeof(B), typeof(C)});
    

    With example output:

    <AList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <ListOfBs>
        <B />
        <B xsi:type="C" />
      </ListOfBs>
    </AList>
    

    The more elegant is:

    XmlAttributeOverrides aor = new XmlAttributeOverrides();
    XmlAttributes listAttribs = new XmlAttributes();
    listAttribs.XmlElements.Add(new XmlElementAttribute("b", typeof(B)));
    listAttribs.XmlElements.Add(new XmlElementAttribute("c", typeof(C)));
    aor.Add(typeof(AList), "ListOfBs", listAttribs);
    
    XmlSerializer ser = new XmlSerializer(typeof(AList), aor);
    

    With example output:

    <AList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <b />
      <c />
    </AList>
    

    In either case you must cache and re-use the ser instance; otherwise you will haemorrhage memory from dynamic compilation.

    0 讨论(0)
  • 2020-11-27 05:40

    I'm don't think attributes can be applied at runtime, as they are used to create Meta-data at the CIL code.

    0 讨论(0)
提交回复
热议问题