System.Version未序列化

时间:2010-01-18 12:13:18

标签: c# xml serialization version

我有一个System.Version属性的类,如下所示:

    • Build:111
    • 专业:1
    • MajorRevision:0
    • 轻微:1
    • MinorRevision:10
    • 修订版:10

当我序列化类时,版本总是空的:

<Version />

Client类看起来像:

[Serializable]
public class Client
{
    public string Description;
    public string Directory;
    public DateTime ReleaseDate;
    public Version Version;
}

6 个答案:

答案 0 :(得分:16)

System.Version不可序列化,如果你查看it's properties on MSDN,你会发现它们没有setter ...所以序列化程序不会存储它们。但是,this approach still works。那篇文章(旧的,但仍然有效)提供了一个可序列化的Version类,你可以切换到那个并继续吗?

由tomfanning编辑
我已经从archive.org中删除了死网站上的代码,转载如下。

using System;
using System.Globalization;
namespace CubicOrange.Version
{
    /// <summary>
    /// Serializable version of the System.Version class.
    /// </summary>
    [Serializable]
    public class ModuleVersion : ICloneable, IComparable
    {
        private int major;
        private int minor;
        private int build;
        private int revision;
        /// <summary>
        /// Gets the major.
        /// </summary>
        /// <value></value>
        public int Major
        {
            get
            {
                return major;
            }
            set
            {
                major = value;
            }
        }
        /// <summary>
        /// Gets the minor.
        /// </summary>
        /// <value></value>
        public int Minor
        {
            get
            {
                return minor;
            }
            set
            {
                minor = value;
            }
        }
        /// <summary>
        /// Gets the build.
        /// </summary>
        /// <value></value>
        public int Build
        {
            get
            {
                return build;
            }
            set
            {
                build = value;
            }
        }
        /// <summary>
        /// Gets the revision.
        /// </summary>
        /// <value></value>
        public int Revision
        {
            get
            {
                return revision;
            }
            set
            {
                revision = value;
            }
        }
        /// <summary>
        /// Creates a new <see cref="ModuleVersion"/> instance.
        /// </summary>
        public ModuleVersion()
        {
            this.build = -1;
            this.revision = -1;
            this.major = 0;
            this.minor = 0;
        }
        /// <summary>
        /// Creates a new <see cref="ModuleVersion"/> instance.
        /// </summary>
        /// <param name="version">Version.</param>
        public ModuleVersion(string version)
        {
            this.build = -1;
            this.revision = -1;
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }
            char[] chArray1 = new char[1] { '.' };
            string[] textArray1 = version.Split(chArray1);
            int num1 = textArray1.Length;
            if ((num1 < 2) || (num1 > 4))
            {
                throw new ArgumentException("Arg_VersionString");
            }
            this.major = int.Parse(textArray1[0], CultureInfo.InvariantCulture);
            if (this.major < 0)
            {
                throw new ArgumentOutOfRangeException("version", "ArgumentOutOfRange_Version");
            }
            this.minor = int.Parse(textArray1[1], CultureInfo.InvariantCulture);
            if (this.minor < 0)
            {
                throw new ArgumentOutOfRangeException("version", "ArgumentOutOfRange_Version");
            }
            num1 -= 2;
            if (num1 > 0)
            {
                this.build = int.Parse(textArray1[2], CultureInfo.InvariantCulture);
                if (this.build < 0)
                {
                    throw new ArgumentOutOfRangeException("build", "ArgumentOutOfRange_Version");
                }
                num1--;
                if (num1 > 0)
                {
                    this.revision = int.Parse(textArray1[3], CultureInfo.InvariantCulture);
                    if (this.revision < 0)
                    {
                        throw new ArgumentOutOfRangeException("revision", "ArgumentOutOfRange_Version");
                    }
                }
            }
        }
        /// <summary>
        /// Creates a new <see cref="ModuleVersion"/> instance.
        /// </summary>
        /// <param name="major">Major.</param>
        /// <param name="minor">Minor.</param>
        public ModuleVersion(int major, int minor)
        {
            this.build = -1;
            this.revision = -1;
            if (major < 0)
            {
                throw new ArgumentOutOfRangeException("major", "ArgumentOutOfRange_Version");
            }
            if (minor < 0)
            {
                throw new ArgumentOutOfRangeException("minor", "ArgumentOutOfRange_Version");
            }
            this.major = major;
            this.minor = minor;
            this.major = major;
        }
        /// <summary>
        /// Creates a new <see cref="ModuleVersion"/> instance.
        /// </summary>
        /// <param name="major">Major.</param>
        /// <param name="minor">Minor.</param>
        /// <param name="build">Build.</param>
        public ModuleVersion(int major, int minor, int build)
        {
            this.build = -1;
            this.revision = -1;
            if (major < 0)
            {
                throw new ArgumentOutOfRangeException("major", "ArgumentOutOfRange_Version");
            }
            if (minor < 0)
            {
                throw new ArgumentOutOfRangeException("minor", "ArgumentOutOfRange_Version");
            }
            if (build < 0)
            {
                throw new ArgumentOutOfRangeException("build", "ArgumentOutOfRange_Version");
            }
            this.major = major;
            this.minor = minor;
            this.build = build;
        }
        /// <summary>
        /// Creates a new <see cref="ModuleVersion"/> instance.
        /// </summary>
        /// <param name="major">Major.</param>
        /// <param name="minor">Minor.</param>
        /// <param name="build">Build.</param>
        /// <param name="revision">Revision.</param>
        public ModuleVersion(int major, int minor, int build, int revision)
        {
            this.build = -1;
            this.revision = -1;
            if (major < 0)
            {
                throw new ArgumentOutOfRangeException("major", "ArgumentOutOfRange_Version");
            }
            if (minor < 0)
            {
                throw new ArgumentOutOfRangeException("minor", "ArgumentOutOfRange_Version");
            }
            if (build < 0)
            {
                throw new ArgumentOutOfRangeException("build", "ArgumentOutOfRange_Version");
            }
            if (revision < 0)
            {
                throw new ArgumentOutOfRangeException("revision", "ArgumentOutOfRange_Version");
            }
            this.major = major;
            this.minor = minor;
            this.build = build;
            this.revision = revision;
        }
        #region ICloneable Members
        /// <summary>
        /// Clones this instance.
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            ModuleVersion version1 = new ModuleVersion();
            version1.major = this.major;
            version1.minor = this.minor;
            version1.build = this.build;
            version1.revision = this.revision;
            return version1;
        }
        #endregion
        #region IComparable Members
        /// <summary>
        /// Compares to.
        /// </summary>
        /// <param name="obj">Obj.</param>
        /// <returns></returns>
        public int CompareTo(object version)
        {
            if (version == null)
            {
                return 1;
            }
            if (!(version is ModuleVersion))
            {
                throw new ArgumentException("Arg_MustBeVersion");
            }
            ModuleVersion version1 = (ModuleVersion)version;
            if (this.major != version1.Major)
            {
                if (this.major > version1.Major)
                {
                    return 1;
                }
                return -1;
            }
            if (this.minor != version1.Minor)
            {
                if (this.minor > version1.Minor)
                {
                    return 1;
                }
                return -1;
            }
            if (this.build != version1.Build)
            {
                if (this.build > version1.Build)
                {
                    return 1;
                }
                return -1;
            }
            if (this.revision == version1.Revision)
            {
                return 0;
            }
            if (this.revision > version1.Revision)
            {
                return 1;
            }
            return -1;
        }
        #endregion
        /// <summary>
        /// Equalss the specified obj.
        /// </summary>
        /// <param name="obj">Obj.</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if ((obj == null) || !(obj is ModuleVersion))
            {
                return false;
            }
            ModuleVersion version1 = (ModuleVersion)obj;
            if (((this.major == version1.Major) && (this.minor == version1.Minor)) && (this.build == version1.Build) && (this.revision == version1.Revision))
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// Gets the hash code.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            int num1 = 0;
            num1 |= ((this.major & 15) << 0x1c);
            num1 |= ((this.minor & 0xff) << 20);
            num1 |= ((this.build & 0xff) << 12);
            return (num1 | this.revision & 0xfff);
        }
        /// <summary>
        /// Operator ==s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator ==(ModuleVersion v1, ModuleVersion v2)
        {
            return v1.Equals(v2);
        }
        /// <summary>
        /// Operator &gt;s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator >(ModuleVersion v1, ModuleVersion v2)
        {
            return (v2 < v1);
        }
        /// <summary>
        /// Operator &gt;=s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator >=(ModuleVersion v1, ModuleVersion v2)
        {
            return (v2 <= v1);
        }
        /// <summary>
        /// Operator !=s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator !=(ModuleVersion v1, ModuleVersion v2)
        {
            return (v1 != v2);
        }
        /// <summary>
        /// Operator &lt;s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator <(ModuleVersion v1, ModuleVersion v2)
        {
            if (v1 == null)
            {
                throw new ArgumentNullException("v1");
            }
            return (v1.CompareTo(v2) < 0);
        }
        /// <summary>
        /// Operator &lt;=s the specified v1.
        /// </summary>
        /// <param name="v1">V1.</param>
        /// <param name="v2">V2.</param>
        /// <returns></returns>
        public static bool operator <=(ModuleVersion v1, ModuleVersion v2)
        {
            if (v1 == null)
            {
                throw new ArgumentNullException("v1");
            }
            return (v1.CompareTo(v2) <= 0);
        }
        /// <summary>
        /// Toes the string.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (this.build == -1)
            {
                return this.ToString(2);
            }
            if (this.revision == -1)
            {
                return this.ToString(3);
            }
            return this.ToString(4);
        }
        /// <summary>
        /// Toes the string.
        /// </summary>
        /// <param name="fieldCount">Field count.</param>
        /// <returns></returns>
        public string ToString(int fieldCount)
        {
            object[] objArray1;
            switch (fieldCount)
            {
                case 0:
                    {
                        return string.Empty;
                    }
                case 1:
                    {
                        return (this.major.ToString());
                    }
                case 2:
                    {
                        return (this.major.ToString() + "." + this.minor.ToString());
                    }
            }
            if (this.build == -1)
            {
                throw new ArgumentException(string.Format("ArgumentOutOfRange_Bounds_Lower_Upper {0},{1}", "0", "2"), "fieldCount");
            }
            if (fieldCount == 3)
            {
                objArray1 = new object[5] { this.major, ".", this.minor, ".", this.build };
                return string.Concat(objArray1);
            }
            if (this.revision == -1)
            {
                throw new ArgumentException(string.Format("ArgumentOutOfRange_Bounds_Lower_Upper {0},{1}", "0", "3"), "fieldCount");
            }
            if (fieldCount == 4)
            {
                objArray1 = new object[7] { this.major, ".", this.minor, ".", this.build, ".", this.revision };
                return string.Concat(objArray1);
            }
            throw new ArgumentException(string.Format("ArgumentOutOfRange_Bounds_Lower_Upper {0},{1}", "0", "4"), "fieldCount");
        }
    }
}

答案 1 :(得分:12)

我更喜欢使用下面的方法,所以我的类中只有一个Type VersionXml属性。隐式运算符在这里非常有用。

[Serializable]
[XmlType("Version")]
public class VersionXml
{
    public VersionXml()
    {
        this.Version = null;
    }

    public VersionXml(Version Version)
    {
        this.Version = Version;
    }

    [XmlIgnore]
    public Version Version { get; set; }

    [XmlText]
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    public string Value
    {
        get { return this.Version == null ? string.Empty : this.Version.ToString(); }
        set
        {
            Version temp;
            Version.TryParse(value, out temp);
            this.Version = temp;
        }
    }

    public static implicit operator Version(VersionXml VersionXml)
    {
        return VersionXml.Version;
    }

    public static implicit operator VersionXml(Version Version)
    {
        return new VersionXml(Version);
    }

    public override string ToString()
    {
        return this.Value;
    }
}

答案 2 :(得分:6)

您可以使用字符串代理属性:

[XmlIgnore]
public System.Version Version { get; set; }
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public string version 
{
    get 
    {
        if (this.Version == null)
            return string.Empty;
        else
            return this.Version.ToString();
    }
    set 
    {
        if(!String.IsNullOrEmpty(value))
           this.Version = new Version(value);
    } 
}

答案 3 :(得分:1)

您需要定义getset个访问者,如下:

public class Version
{
    public int Build { get; set; }
    public int Major { get; set; }
    public int MajorRevision { get; set; }
    public int Minor { get; set; }
    public int MinorRevision { get; set; }
    public int Revision { get; set; }
}

// ...

new XmlSerializer(typeof (Version))
    .Serialize(Console.Out,
               new Version()
                   {
                       Build = 111,
                       Major = 1,
                       MajorRevision = 0,
                       Minor = 1,
                       MinorRevision = 10,
                       Revision = 10
                   }
    );

我得到了这个输出:

<?xml version="1.0" encoding="ibm850"?>
<Version xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Build>111</Build>
  <Major>1</Major>
  <MajorRevision>0</MajorRevision>
  <Minor>1</Minor>
  <MinorRevision>10</MinorRevision>
  <Revision>10</Revision>
</Version>

答案 4 :(得分:1)

更准确地说,System.Version不是 XML - 可序列化。 可序列化BinaryFormatter,例如:

Version version = new Version(1, 2, 3, 4);

using (MemoryStream stream = new MemoryStream())
{
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, version);

    stream.Position = 0;

    Version deserialized = (Version)formatter.Deserialize(stream);
}

答案 5 :(得分:1)

我已经清理了Nick Craver的实现更加简洁和可读,添加了XML序列化支持(使用属性而不是单独的元素),实现了字符串TypeConverter以及修复了一些可能存在NullReferenceExceptions或者NullReferenceExceptions的比较问题。无限循环(从内部调用重载运算符)。

我也使用了一些C#6功能。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Xml.Serialization;

[Serializable]
[TypeConverter(typeof(VersionCodeConverter))]
public class VersionCode : ICloneable, IComparable<VersionCode>, IEquatable<VersionCode>
{
  [XmlAttribute] public int Major { get; private set; }
  [XmlAttribute] public int Minor { get; private set; }
  [XmlAttribute] public int Build { get; private set; } = -1;
  [XmlAttribute] public int Revision { get; private set; } = -1;

  public VersionCode() { }

  public VersionCode(int major, int minor, int build = 0, int revision = 0)
  {
    if (major < 0)
      throw new ArgumentOutOfRangeException(nameof(major), $"{nameof(major)} cannot be less than 0");

    if (minor < 0)
      throw new ArgumentOutOfRangeException(nameof(minor), $"{nameof(minor)} cannot be less than 0");

    if (build < 0)
      throw new ArgumentOutOfRangeException(nameof(build), $"{nameof(build)} cannot be less than 0");

    if (revision < 0)
      throw new ArgumentOutOfRangeException(nameof(revision), $"{nameof(revision)} cannot be less than 0");

    Major = major;
    Minor = minor;
    Build = build;
    Revision = revision;
  }

  public VersionCode(string version)
  {
    if (version == null)
      throw new ArgumentNullException(nameof(version));

    var components = new Stack<string>(version.Split('.'));

    if (components.Count < 2 || components.Count > 4)
      throw new ArgumentException(nameof(version));

    Major = int.Parse(components.Pop(), CultureInfo.InvariantCulture);

    if (Major < 0)
      throw new ArgumentOutOfRangeException(nameof(version), $"{nameof(Major)} cannot be less than 0");

    Minor = int.Parse(components.Pop(), CultureInfo.InvariantCulture);

    if (Minor < 0)
      throw new ArgumentOutOfRangeException(nameof(version), $"{nameof(Minor)} cannot be less than 0");

    if (!components.Any())
      return;

    Build = int.Parse(components.Pop(), CultureInfo.InvariantCulture);

    if (Build < 0)
      throw new ArgumentOutOfRangeException(nameof(version), $"{nameof(Build)} cannot be less than 0");

    if (!components.Any())
      return;

    Revision = int.Parse(components.Pop(), CultureInfo.InvariantCulture);

    if (Revision < 0)
      throw new ArgumentOutOfRangeException(nameof(version), $"{nameof(Revision)} cannot be less than 0");
  }

  public object Clone()
    => new VersionCode(Major, Minor, Build, Revision);

  public int CompareTo(VersionCode version) 
    => Major != version.Major ? Major.CompareTo(version.Major)
      : Minor != version.Minor ? Minor.CompareTo(version.Minor)
        : Build != version.Build ? Build.CompareTo(version.Build)
          : Revision.CompareTo(version.Revision);

  public override bool Equals(object obj)
    => obj is VersionCode && Equals((VersionCode)obj);

  public bool Equals(VersionCode version)
    => Major == version.Major
    && Minor == version.Minor
    && Build == version.Build
    && Revision == version.Revision;

  public override int GetHashCode()
  {
    var hash = 0;

    hash |= (Major & 15) << 0x1c;
    hash |= (Minor & 0xff) << 20;
    hash |= (Build & 0xff) << 12;
    hash |= (Revision & 0xfff);

    return hash;
  }

  public static bool operator ==(VersionCode v1, VersionCode v2)
    => ReferenceEquals(v1, null) ? ReferenceEquals(v2, null) : v1.Equals(v2);

  public static bool operator !=(VersionCode v1, VersionCode v2)
    => !(v1 == v2);

  public static bool operator >(VersionCode v1, VersionCode v2)
    => v2 < v1;

  public static bool operator >=(VersionCode v1, VersionCode v2)
    => v2 <= v1;

  public static bool operator <(VersionCode v1, VersionCode v2)
    => !ReferenceEquals(v1, null) && v1.CompareTo(v2) < 0;

  public static bool operator <=(VersionCode v1, VersionCode v2)
    => !ReferenceEquals(v1, null) && v1.CompareTo(v2) <= 0;

  public override string ToString()
    => Build < 0 ? $"{Major}.{Minor}"
      : Revision < 0 ? $"{Major}.{Minor}.{Build}"
        : $"{Major}.{Minor}.{Build}.{Revision}";
}

public class VersionCodeConverter : TypeConverter
{
  public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    => sourceType == typeof(string)
    || base.CanConvertFrom(context, sourceType);

  public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  {
    var version = value as string;

    return version != null 
      ? new VersionCode(version)
      : base.ConvertFrom(context, culture, value);
  }
}