2010-01-18 25 views
26

我有一个System.Version属性的类,它看起来像这样:System.Version没有序列号

  • 版本
    • 体形: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; 
} 
+0

请问您可以发布您的班级定义吗? – 2010-01-18 12:14:14

+0

请看我编辑上面 – MysticEarth 2010-01-18 12:16:33

回答

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"); 
     } 
    } 
} 
+0

那个班帮我出去了!谢谢! – MysticEarth 2010-01-18 12:21:46

+0

原文http://dotnet.org.za/armand/archive/2004/09/17/4077.aspx似乎不再存在。你可以直接在StackOverflow上发布解决方案吗? – 2011-04-11 23:54:27

+0

我刚刚从死网站的代码更新了帖子。 – tomfanning 2012-02-08 14:38:51

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> 
+0

工作也是如此,但我使用了Nick Craver建议的课程。谢谢!!! – MysticEarth 2010-01-18 12:22:21

+0

对不起,我没有注意到你正在使用'System.Version' – 2010-01-18 12:23:34

1

更确切地说,System.VersionXML可序列化。这序列化与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); 
} 
4

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

[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); 
    } 
} 
11

我更喜欢下面的使用方法,所以我必须在只有一个属性与类型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; 
    } 
} 
+1

非常整洁的解决方案!只是提示任何人想知道如何使用它:'[XmlElement(Type = typeof(VersionXml))] public Version SomeVersionProperty {get;组; }' – lxa 2016-04-04 18:22:37

+1

你可以使用public VersionXml SomeVersionProperty {get;组; }并使用a.SomeVersionProperty = new Version(...),因为VersionXml类中存在隐式运算符 – yclkvnc 2016-04-05 06:36:21

1

我已经清除了尼克Craver的实施更加简明易读,新增XML序列化的支持(属性,而不是单独的元素),实现一个字符串类型转换器以及固定的一对夫妇的比较问题,即有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); 
    } 
} 
+0

我相信你的构造函数通过使用Stack来取错顺序。 我们使用队列来代替: public VersionCode(string version) { var components = new Queue (version.Split('。')); Major = int.Parse(components.Dequeue(),CultureInfo.InvariantCulture); ... – user1613512 2018-02-13 07:01:38