【问题标题】:SerializationException Type "is not marked as serializable" - But it isSerializationException 类型“未标记为可序列化” - 但它是
【发布时间】:2012-07-15 12:11:25
【问题描述】:

在 Windows 窗体、.NET Framework 4.0 中,我正在尝试序列化我编写的类的实例。

该类被标记为可序列化,但使用该类的表单(显然)不是。

我不想序列化表单的实例。我想序列化我课堂上的数据。

我班级中的所有内容都标记为可序列化,那么为什么我仍然收到 SerializationException?

(点击>> HERE <<在新窗口中打开图片全尺寸)

更新:

这是我的BrazierCuttoff 类和相关部分:

[Serializable()]
public class BrazierCuttoff : IEquatable<BrazierCuttoff> {
  private int qty;
  private int[] joint, pass, shift;
  private float mult;
  private BrazierPay a, b, c, d, e;
  public event EventHandler BrazierCuttoffChanged;
  public const int MAXIMUMSMALLQUANTITY = 20;
  EnumeratedLevel[,] eLvArray;
  /// <summary>
  /// Gets or Sets the Brazier Matrix values
  /// </summary>
  /// <param name="passRatioIndex">0=100%,1=95,2=90,3=85,4=80,5=75,6=70,7=65</param>
  /// <param name="minJointIndex">0=900,1=1200,2=1400,3=1600,4=1800,5=2000,6=2100,=2200</param>
  /// <returns>Brazier Matrix value</returns>
  public EnumeratedLevel this[int passRatioIndex, int minJointIndex] {
    get { return eLvArray[passRatioIndex, minJointIndex]; }
    set { eLvArray[passRatioIndex, minJointIndex] = value; }
  }
  /// <summary>
  /// Initializes a new Form Values object using default values
  /// </summary>
  public BrazierCuttoff() {
    A = new BrazierPay(5.0f);
    B = new BrazierPay(4.0f);
    C = new BrazierPay(3.0f);
    D = new BrazierPay(2.0f);
    E = new BrazierPay(1.0f);
    NA = new BrazierPay(0.0f);
    ShiftMinimum = new int[] { 12, 12, 12 };
    PassRatio = new int[] { 100, 95, 90, 85, 80, 75, 70, 65 };
    JointMinimum = new int[] { 900, 1200, 1400, 1600, 1800, 2000, 2100, 2200 };
    eLvArray = new EnumeratedLevel[8, 8];
    EnumeratedLevel level = EnumeratedLevel.NA_Silver;
    for (int y = 0; y < 8; y++) {
      for (int x = 0; x < 8; x++) {
        switch (y) {
          case 0: level = (x < 2) ? EnumeratedLevel.B_Blue : EnumeratedLevel.A_Violet; break;
          case 1: level = (x == 0) ? EnumeratedLevel.C_Green : (x < 3) ? EnumeratedLevel.B_Blue : EnumeratedLevel.A_Violet; break;
          case 2: level = (x < 2) ? EnumeratedLevel.C_Green : (x < 5) ? EnumeratedLevel.B_Blue : EnumeratedLevel.A_Violet; break;
          case 3: level = (x == 0) ? EnumeratedLevel.D_Yellow : (x < 4) ? EnumeratedLevel.C_Green : (x < 6) ? EnumeratedLevel.B_Blue : EnumeratedLevel.A_Violet; break;
          case 4: level = (x < 2) ? EnumeratedLevel.D_Yellow : (x < 5) ? EnumeratedLevel.C_Green : EnumeratedLevel.B_Blue; break;
          case 5: level = (x == 0) ? EnumeratedLevel.E_Orange : (x < 3) ? EnumeratedLevel.D_Yellow : (x < 6) ? EnumeratedLevel.C_Green : EnumeratedLevel.B_Blue; break;
          case 6: level = (x < 2) ? EnumeratedLevel.E_Orange : (x < 5) ? EnumeratedLevel.D_Yellow : EnumeratedLevel.C_Green; break;
          default: level = (x == 0) ? EnumeratedLevel.NA_Silver : (x < 5) ? EnumeratedLevel.E_Orange : EnumeratedLevel.D_Yellow; break;
        }
        eLvArray[x, y] = level;
      }
    }
  }

  private void broadcast() {
    if (BrazierCuttoffChanged != null) {
      BrazierCuttoffChanged(this, new EventArgs());
    }
  }
  /// <summary>
  /// Gets or Sets the A Pay Level data
  /// </summary>
  public BrazierPay A { get { return a; } set { if (a != value) { a = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the B Pay Level data
  /// </summary>
  public BrazierPay B { get { return b; } set { if (b != value) { b = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the C Pay Level data
  /// </summary>
  public BrazierPay C { get { return c; } set { if (c != value) { c = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the D Pay Level data
  /// </summary>
  public BrazierPay D { get { return d; } set { if (d != value) { d = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the E Pay Level data
  /// </summary>
  public BrazierPay E { get { return e; } set { if (e != value) { e = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the N/A Pay Level data
  /// </summary>
  public BrazierPay NA { get; private set; }

  public void Refresh() {
    const float delta = 0.01f;
    while (A.Dirty || B.Dirty || C.Dirty || D.Dirty || E.Dirty) {
      if (A.Dirty) {
        if (A.Value <= B.Value) B.Value = A.Value - delta;
        A.Dirty = false;
      } else if (B.Dirty) {
        if (B.Value <= C.Value) C.Value = B.Value - delta;
        if (A.Value <= B.Value) A.Value = B.Value + delta;
        B.Dirty = false;
      } else if (C.Dirty) {
        if (C.Value <= D.Value) D.Value = C.Value - delta;
        if (B.Value <= C.Value) B.Value = C.Value + delta;
        C.Dirty = false;
      } else if (D.Dirty) {
        if (D.Value <= E.Value) E.Value = D.Value - delta;
        if (C.Value <= D.Value) C.Value = D.Value + delta;
        D.Dirty = false;
      } else if (E.Dirty) {
        if (D.Value <= E.Value) D.Value = E.Value + delta;
        E.Dirty = false;
      }
    }
  }
  /// <summary>
  /// Gets the minimum Average Joints requirement
  /// </summary>
  public int AverageJoints { get { return JointMinimum[0]; } }
  /// <summary>
  /// Gets the minimum Chamber Pass Ratio requirement
  /// </summary>
  public int FirstTimePassRate { get { return PassRatio[PassRatio.Length - 1]; } }
  /// <summary>
  /// Gets or sets the Minimum Average Joints requirements (Range: 0 @ 900 to 7 @ 2200)
  /// </summary>
  public int[] JointMinimum { get { return joint; } set { if (joint != value) { joint = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the Chamber Pass Ratio levels (Range: 0 @ 100% to 7 @ 65%)
  /// </summary>
  public int[] PassRatio { get { return pass; } set { if (pass != value) { pass = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the Integral Array of minimum shifts required to qualify for a bonus
  /// </summary>
  public int[] ShiftMinimum { get { return shift; } set { if (shift != value) { shift = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the Small Workorder Multiplier (1 is default/disable)
  /// </summary>
  public float SmallWoMulti { get { return mult; } set { if (mult != value) { mult = value; broadcast(); } } }
  /// <summary>
  /// Gets or Sets the Small Workorder Quantity value (0 is disable)
  /// </summary>
  public int SmallWoQty { get { return qty; } set { if (qty != value) { qty = value; broadcast(); } } }

  #region IEquatable<BrazierCuttoff> Members

  public bool Equals(BrazierCuttoff other) {
    if (other != null) {
      if ((A == other.A) && (B == other.B) && (C == other.C) && (D == other.D) && (E == other.E) && (NA == other.NA)) {
        if ((ShiftMinimum == other.ShiftMinimum) && (PassRatio == other.PassRatio) && (JointMinimum == other.JointMinimum)) {
          return (eLvArray == other.eLvArray);
        }
      }
    }
    return false;
  }

  #endregion

}

这是上面类中使用的BrazierPay 对象:

[Serializable()]
public class BrazierPay {
  float pay;
  public BrazierPay(float payLevel) {
    Dirty = false;
    pay = payLevel;
  }
  public float Value {
    get { return pay; }
    set {
      if (pay != value) {
        Dirty = true;
        pay = value;
      }
    }
  }
  public bool Dirty { get; set; }
  public string DollarValue { get { return string.Format("{0:C}", pay); } }
  public string Formatted { get { return string.Format("{0:F}", pay); } }
  public override string ToString() { return Formatted; }
}

我什至将此枚举类型标记为可序列化(尽管它不应该需要它):

[Serializable()]
public enum EnumeratedLevel {
  NA_Silver = Clicker.NA_Silver, // Color.Silver
  E_Orange = Clicker.E_Orange, // Color.Orange
  D_Yellow = Clicker.D_Yellow, // Color.Yellow
  C_Green = Clicker.C_Green, // Color.Lime
  B_Blue = Clicker.B_Blue, // Color.DodgerBlue
  A_Violet = Clicker.A_Violet, // Color.Violet
}

【问题讨论】:

  • 看起来您正在尝试序列化继承自 Form 的内容?您提供的部分定义的一半未标记为Serializable。你会发现很难序列化从你无法控制的其他东西继承的东西,很多东西没有标记为可序列化,你将无法改变它。 Form 就是这样一类。
  • BrazierCuttoff 类有一个EventHandler,使我能够对数据的更改进行编码。这会导致我的问题吗?如果是这样,我将如何将 EventHandler 从我的班级中排除?我的课程应该很快就会发布。

标签: c# winforms serialization


【解决方案1】:

已解决

我需要为 EventHandler 设置一个NonSerializedAttribute

无法在类中序列化事件委托(请参阅Delegates and Serialization)。

将字段标记为NonSerializedAttribute 听起来很简单。

在我的代码中,我只是添加了这一行:

[field:NonSerializedAttribute()]
public event EventHandler BrazierCuttoffChanged;

【讨论】:

  • 很好地找到了答案,当我看到您对活动的评论时,我正要发布这个。订阅列表默认是序列化的,所以你需要忽略它。
  • 您是如何发现这一点的?通过某种方式调试?
  • @Protectorone - 在我关于委托和序列化的 Google 搜索结果中,我在上面引用了 Microsoft 链接。可悲的是,就像很多微软的东西一样,他们删除了链接。我无法想象保存这样的档案需要太多的存储空间,但无论如何它们都会删除东西。
  • @Protectorone - 另外,是的,我在调试器中发现了这个异常。我注意到我永远无法反序列化我保存的状态,所以我进入了序列化(保存)和反序列化(获取)方法的过程。一旦我发现我有一个 SerializationException,我就开始搜索消息文本 “未标记为可序列化。”
【解决方案2】:

这是任何 JSON 序列化都可能遇到的问题,包括 MVC 4 中的 Web API。

我发现这篇文章在我获得序列化时非常有用,除了 const int 值。任何 const 值都需要使用与 Nick Freeman 的答案相同的属性进行标记:

[field: NonSerializedAttribute]
const int iCantBeSerialized = 1;

【讨论】:

    【解决方案3】:
    [field:NonSerializedAttribute()]
    public event EventHandler BrazierCuttoffChanged;
    

    有同样的问题,我的可序列化 NotifyObject 基类的 PropertyChanged EventHandler 被一些视图模型订阅,因此进入序列化队列。将 NonSerializedAddtribute 添加到此 EventHandler 节省了我的时间。 :-)

    【讨论】:

      【解决方案4】:

      BrazierMatrix2标记为[Serializable]

      【讨论】:

      • BrazierMatrix2 是包含我的数据类实例的表单。我想要序列化的是BrazierCuttoff(标记为可序列化)中的数据。表单不需要为此可序列化......应该吗? :困惑:
      • 你使用了错误的表单架构,你必须划分模型,控制器和视图阅读mvvm,mvc之类的模式设计
      • 首先,反对票不是来自我。我支持所有努力回答我的问题的人。其次,你能解释一下关于 mwm/mvc 的评论吗? (不熟悉这些缩写词)。
      • 这是应用程序可视化部分的设计模式,你可以在这里阅读它en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controlleren.wikipedia.org/wiki/Model_View_ViewModel它是devide data classe,manager classes and view classes,如果你会使用这个模式,你会不要面对这个和类似的问题
      • 您遇到了这个问题,因为您的架构存在一些组织问题,这种模式可以帮助您创建好的解决方案,但它会更长更难
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 2019-12-15
      相关资源
      最近更新 更多