简体   繁体   中英

Error on XML serializing on a non-serializable object on a non-serialized method

I'm using this code

XmlSerializer xs = new XmlSerializer(typeof(T));

To serialize an object.

Now I get an error on this line of code (which is in an object nested way down in the to be serialized object)

public override List<BrokenRule> GetBrokenRules() {

the error is Csla.Validation.BrokenRule cannot be serialized because it does not have a parameterless constructor.

Now that is correct, but I thought methods were not serialized, so what is the problem (the Csla.Validation.BrokenRule is not used elsewhere)

If it is by design, this behavior, is there a way to runtime say "ignore this part of the object"?

Editing the objects code with attributes etc. is not allowed....

One way you could serialize this class to XML is to create an XmlSerializer for the derived class and pass XmlAttributeOverrides that specify that the property which returns a class is XmlIgnore . However, as specified in the documentation , you must cache and re-use this XmlSerializer :

To increase performance, the XML serialization infrastructure dynamically generates assemblies to serialize and deserialize specified types. The infrastructure finds and reuses those assemblies. This behavior occurs only when using the following constructors:

XmlSerializer.XmlSerializer(Type)

XmlSerializer.XmlSerializer(Type, String)

If you use any of the other constructors, multiple versions of the same assembly are generated and never unloaded, which results in a memory leak and poor performance. The easiest solution is to use one of the previously mentioned two constructors. Otherwise, you must cache the assemblies in a Hashtable, as shown in the following example.

Rather than a HashTable , in simple cases I will construct my XmlSerializer in the static constructor for the class I need to serialize. This is fairly lazy, and is guaranteed to be thread safe. Thus, for instance:

public class NoParameterlessConstructor
{
    public string Value { get; set; }

    public NoParameterlessConstructor(string value)
    {
        this.Value = value;
    }
}

public class BaseClass
{
    public NoParameterlessConstructor NoParameterlessConstructor { get; set; }
}

public class DerivedClass : BaseClass
{
    static XmlSerializer serializer = null;

    static DerivedClass()
    {
        var xOver = new XmlAttributeOverrides();
        var attrs = new XmlAttributes() { XmlIgnore = true };
        xOver.Add(typeof(BaseClass), "NoParameterlessConstructor", attrs); // Must use BaseClass here not DerivedClass!

        serializer = new XmlSerializer(typeof(DerivedClass), xOver);
    }

    public static XmlSerializer DerivedClassXmlSerializer { get { return serializer; } }

    public int Id { get; set; }
}

And then, to test:

public static class TestNoParameterlessConstructor
{
    public static void Test()
    {
        var derived = new DerivedClass { Id = 1, NoParameterlessConstructor = new NoParameterlessConstructor("Test") };
        var xml = XmlSerializationHelper.GetXml(derived, DerivedClass.DerivedClassXmlSerializer);
        Debug.WriteLine(xml);
    }
}

which outputs

<?xml version="1.0" encoding="utf-16"?>
<DerivedClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Id>1</Id>
</DerivedClass>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM