2011-05-10 23 views
0

我创建了一个非常简单的控件,其中包含过滤器选项控件列表,其方式与listbox具有listitems列表的方式大致相同。无法xml序列化自定义对象

我有一些麻烦tring让它序列化到视图状态,因为序列化程序似乎试图序列化基类属性,基本上我最终会出现像 - 无法序列化属性“页”的错误你是什么想想是我的问题?

验证码:

[Serializable] 
public class FilterOption : Control, ISerializable 
{ 
    public event EventHandler Checkchanged; 

    CheckBox _chk = new CheckBox(); 
    Label _lbl = new Label(); 

    public string Text 
    { 
     get { return _lbl.Text; } 
     set { _lbl.Text = value; } 
    } 

    public bool Checked 
    { 
     get { return _chk.Checked; } 
     set { _chk.Checked = value; } 
    } 

    public FilterOption() 
    { 
     Controls.Add(new LiteralControl("<li>")); 
     _chk.AutoPostBack = true; 
     _chk.CssClass = "checkbox"; 
     Controls.Add(_chk); 
     Controls.Add(_lbl); 
     _chk.CheckedChanged += new EventHandler(_chk_CheckedChanged); 
     Controls.Add(new LiteralControl("</li>")); 
    } 

    public FilterOption(string Text, bool Checked) 
    { 
     Controls.Add(new LiteralControl("<li>")); 
     _chk.CssClass = "checkbox"; 
     _lbl.Text = Text; 
     _chk.Checked = Checked; 
     Controls.Add(_chk); 
     Controls.Add(_lbl); 
     _chk.CheckedChanged += new EventHandler(_chk_CheckedChanged); 
     Controls.Add(new LiteralControl("</li>")); 
    } 

    public FilterOption(SerializationInfo info, StreamingContext context) 
    { 
     Controls.Add(new LiteralControl("<li>")); 
     _chk.CssClass = "checkbox"; 
     _lbl.Text = (string)info.GetValue("Text", typeof(string)); 
     _chk.Checked = (bool)info.GetValue("Text", typeof(bool)); 
     Controls.Add(_chk); 
     Controls.Add(_lbl); 
     _chk.CheckedChanged += new EventHandler(_chk_CheckedChanged); 
     Controls.Add(new LiteralControl("</li>")); 
    } 

    void _chk_CheckedChanged(object sender, EventArgs e) 
    { 
     if (Checkchanged != null) 
      Checkchanged(this, new EventArgs()); 
    } 


    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     if(info == null) 
      throw new System.ArgumentNullException("info"); 

     info.AddValue("Text", _lbl.Text); 
     info.AddValue("Checked", _chk.Checked); 
    } 
} 

我真的只需要序列化的属性添加到GetObjectData方法序列化信息。

我用下面的代码来执行序列...

List<FilterOption> options = new List<FilterOption>(); 

    ... add some items to the collection ... 

StringWriter writer = new StringWriter(); 
XmlSerializer ser = new XmlSerializer(typeof(List<FilterOption>)); 
ser.Serialize(writer, options); 
ViewState["Options"] = writer.ToString(); 

哦叶......我忘了补充...我得到从这里的信息... http://msdn.microsoft.com/en-us/library/ms973893.aspx

(如果它事项)

...

THX Wardy

回答

0

显然,你不能序列即使您不希望序列化派生类型的不可序列化属性,该类型也会继承非序列化类型。

我认为这应该归类为一个错误,因为像ISerializable这样的接口的用户界面是通过手动实现处理序列化的方法来精确指定它是什么。

在任何情况下,我的特定场景的解决方案是根本不打扰序列化,只是简单地将感兴趣的信息保存到视图状态,然后重新使用回发来重新构建完全相同状态的控件,为基于页面回发事件发生。

羞愧这没有更好地记录在某处,因为尽管微软确实记录了页面生命周期的SaveViewState和LoadViewState方法,但他们对如何使用这些事件非常模糊,我猜他们希望社区中的某个人可能提供例。

我会发布我的代码,但它的一个讨厌的黑客得到一切工作,所以我不应该它应该是主流的msdn代码。

好了一个小型的内部应用程序虽然:)

0

您不能序列化您的对象,因为它包含不可序列化的对象。 ASP.NET控件(如CheckBoxLabel)不可序列化。

您应该创建一个对象列表,而不仅仅包含您真正需要的数据,这肯定会是boolean值和string

然后,您必须在每个发布请求中重新创建来自此状态的控件,但是我没有其他方式知道。

[Serializable] 
public class FilterOption 
{ 
    public string MyLabel{get;set;} 
    public bool IsChecked{get;set} 
} 

编辑:

你可以把属性[NonSerialized]上面你不想让系列化成员。

+0

那是永远正确的肯定......不是实施ISerializable接口的点...所以你放什么东西到系列化信息忽略enything是序列化是不能被序列化? ......如果你所说的事实上是真的,那么ISerializable接口有什么意义呢? – War 2011-05-10 09:41:15

+0

虽然我看到你的观点...控件不可序列化...我将自定义控件标记为可序列化,然后实现ISerlializable以确保我只序列化可以序列化的属性值(在这种情况下,为字符串和布尔值)...实际控制本身和基类属性不应该被序列化...还是我错过了什么? – War 2011-05-10 09:51:13

0

你应该看看这个链接,用于XML序列化

http://msdn.microsoft.com/en-us/library/ms950721.aspx

考虑您的意见。我再次搜索,现在我认为您忘记了在GetObjectData()函数中添加此代码。

base.GetObjectData(si,context); 
+0

我不明白这是如何帮助我? ...我不生成基于模式的结果即时通讯尝试查看一个字符串和一个布尔值在viewstate中,然后将其拉回到页面初始化为我的自定义列表控件中的每个项目...我真的不得不使用xml序列化说实话...可以是任何序列化器。 – War 2011-05-10 09:55:04

+0

我不想从基地获取任何东西......在这种情况下,基类是Control类,它导致了我的问题。我从字面上只想要我在自己的GetObjectData方法中指定的数据,而在我的序列化输出中没有其他数据。 – War 2011-05-10 11:10:36

+0

另外值得注意的是,这个错误是在我声明xmlserializer并传入typeof(List )的行中,所以它合理地假设GetObjectData目前甚至没有被调用。 – War 2011-05-10 11:11:51

1

首先,你应该分割你的控制和可序列化的数据。其次,.NET框架包含几个序列类型:从System.Runtime.Serialization[BinaryFormatter][1][SoapFormatter][2]

  1. 序列化工具。这两款折纸机都需要[SerializationAttribute][3]用于您的班级或实施[ISerializable][4]界面(如果您需要更灵活的方式来控制序列化过程)。这些序列化器会序列化当前类的所有专用字段及其所有后代,如果该字段未标记为[NonSerialializedAttribute][5]

注意:此序列化在.net远程处理期间使用。

  1. xml序列化与[XmlSerializer][6]类。在这种情况下,你的类应该有无参数的构造函数,并且这个序列化程序序列化当前类的所有公共读/写属性,以及所有不与[XmlIgnoreAttribute][7]标记的后代。

  2. [DataContractSerializer][8]。该序列化程序要求您的实体应标记为[DataContractAttribute][9],并且所有属性应标记为[DataMemberAttribute][10]。此外,这个串行器可以序列化以前两种方式序列化的类。

总的来说这是非常不好的做法试图序列用户的控制,因为它肯定会包含非序列化的字段(即没有打上NonSerializedAttribute)。所以你肯定会在运行时收到错误信息。

最简单的方法(从设计角度来看更合适)是将单独的可序列化的数据分成单独的类并选择正确的序列化技术。

I.e.如果你想使用XML序列化,你应该为你的类创建参数的构造函数和使用的读/写性能:

public class FilterOption 
{ 
    public FilterOption() {} 

    public string MyLabel{get;set;} 
    public bool IsChecked{get;set;} 
} 

,现在你可以使用以前的代码:

var options = new List<FilterOption> 
{ 
    new FilterOption {MyLabel = "label", IsChecked = false}, 
    new FilterOption {MyLabel = "label2", IsChecked = true} 
}; 
StringWriter writer = new StringWriter(); 
XmlSerializer ser = new XmlSerializer(typeof(List<FilterOption>)); 
ser.Serialize(writer, options); 
+0

有趣的解决方案,你假设我只打算用serializable属性标记我的数据对象,然而我的理解从我的问题中的链接是通过实现ISerializable我可以序列化任何对象,即使是一个继承非序列化类型因为默认情况下,它应该只序列化传递给GetObjectData方法中序列化信息的内容。这不是该界面的目的吗? – War 2011-05-10 11:34:23

+0

是的,但ISerializable接口用于BinnaryFormatter,并且用于配置Xml序列化,您应该实现IXmlSerializable接口:http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx。 – 2011-05-10 11:45:44