6

我有

public bool Included { get; set; }

我想更改为:

public bool IsIncluded { get; set; }

我想要向后兼容。我只想在代码中定义 IsIncluded 但能够读取属性为“包含”的旧 xml。

XmlSerializer 是否支持它以及如何支持?

注意:我试过没有成功......(不反序列化它)

    public bool IsIncluded { get; set; }

    [Obsolete]
    public bool Included
    {
        set { IsIncluded = value; }
        get { return IsIncluded; }
    }

更新我只想补充一点,我更喜欢我的解决方案,因为我希望我的 xml 成为 IsIncluded,这对我来说更合适。像我一样做(下面的解决方案),将使我能够更改 xml,但保持以前的版本正常工作。从长远来看,我可能能够删除代码以支持旧版本。

更新 2018-02-01请查看 Greg Petersen 评论下方的解决方案和建议的解决方案。他提出了一个很好的解决方案,以便将更正封装在应该完成的地方(类)。哇!!!

4

3 回答 3

4

我找到了。我就是这样做的。

// ******************************************************************
public static SimulScenario LoadFromFile(string path)
{
    if (!File.Exists(path))
    {
        return new SimulScenarioError(path);
    }

    SimulScenario simulScenario = null;
    XmlTextReader reader = new XmlTextReader(path);
    XmlSerializer x = new XmlSerializer(typeof(SimulScenario));

    x.UnknownAttribute +=x_UnknownAttribute;
    x.UnknownElement += x_UnknownElement;
    x.UnknownNode += x_UnknownNode;
    x.UnreferencedObject += x_UnreferencedObject;

    try
    {
        simulScenario = (SimulScenario)x.Deserialize(reader);
    }
    catch (Exception)
    {
        return new SimulScenarioError(path);
    }
    finally
    {
        reader.Close();
    }

    return simulScenario;
}

static void x_UnreferencedObject(object sender, UnreferencedObjectEventArgs e)
{

}

static void x_UnknownNode(object sender, XmlNodeEventArgs e)
{

}

static void x_UnknownElement(object sender, XmlElementEventArgs e)
{
    var simulChangeState = e.ObjectBeingDeserialized as SimulChangeState;
    if (simulChangeState != null)
    {
        if (e.Element.Name == "Included")
        {
            bool val;
            if (bool.TryParse(e.Element.InnerText, out val))
            {
                simulChangeState.IsIncluded = val;
            }
            else
            {
                throw new FileFormatException(Log.Instance.AddEntry(LogType.LogError, "Invalid scenario file format."));
            }
        }
    }
}

static void x_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{

}
于 2013-12-19T18:59:57.850 回答
3

试用:

[XmlElement("Included")]
public bool IsIncluded { get; set; }

例子。v1.c的序列化和v2.c的反序列化:

namespace v1
{
    public class c
    {
        public bool Included { get; set; }
    }
}

namespace v2
{
    public class c
    {
        [XmlElement("Included")]
        public bool IsIncluded { get; set; }
    }
}

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            StringWriter sw = new StringWriter();
            new XmlSerializer(typeof(v1.c)).Serialize(sw, new v1.c{ Included=true} );

            StringReader sr = new StringReader( sw.ToString() );
            v2.c cc = (v2.c)new XmlSerializer(typeof(v2.c)).Deserialize(sr);

            Debug.Assert(cc.IsIncluded);
    }
}

}

于 2014-08-22T12:42:10.823 回答
2

我使用了 Eric 的解决方案并进行了一些修改。我添加了一个接口类来处理向后兼容部分。

public interface IBackwardCompatibilitySerializer
{
    void OnUnknownElementFound(string uknownName, string value);
}

使用它,我们只需要像这样编写一次未知元素事件

private static void x_UnknownElement(object sender, XmlElementEventArgs e)
{
    var deserializedObj = (e.ObjectBeingDeserialized as IBackwardCompatibilitySerializer);
    if (deserializedObj == null) return;
    deserializedObj.OnUnknownElementFound(e.Element.Name, e.Element.InnerText);
}

然后,对于要更改变量名称的任何类,让它实现接口。然后你的班级看起来像这样

public class MyClass : IBackwardCompatibilitySerializer 
{
    // public bool Included { get; set; } Old variable

    public bool IsIncluded { get; set; } // New Variable

    public void OnUnknownElementFound(string unknownElement, string value) 
    {
         switch(unknownElement)
         {
              case "Included":
                    IsIncluded = bool.Parse(value);
                    return;
         }
    }
}

Eric,如果您愿意,请随时将其合并到您的解决方案中。

于 2018-02-02T15:54:14.773 回答