【发布时间】:2012-08-28 11:36:57
【问题描述】:
在WebControl 中,我有一个属性Filters 定义如下:
public Dictionary<string, Func<T, bool>> Filters
{
get
{
Dictionary<string, Func<T, bool>> filters =
(Dictionary<string, Func<T, bool>>)ViewState["filters"];
if (filters == null)
{
filters = new Dictionary<string, Func<T, bool>>();
ViewState["filters"] = filters;
}
return filters;
}
}
这个webcontrol是DataSource,我创建这个属性是因为我想有可能轻松过滤数据,例如:
//in page load
DataSource.Filters.Add("userid", u => u.UserID == 8);
但是,如果我将代码更改为以下代码,效果会很好:
//in page load
int userId = int.Parse(DdlUsers.SelectedValue);
DataSource.Filters.Add("userid", u => u.UserID == userId);
它不再工作了,我得到这个错误:
Assembly '...' 中的类型 System.Web.UI.Page 未标记为 可序列化。
发生了什么:
- 序列化程序检查字典。它看到它包含一个匿名委托(这里是 lambda)
- 由于委托是在一个类中定义的,它会尝试序列化整个类,在本例中为 System.Web.UI.Page
- 该类未标记为可序列化
- 因为 3 抛出异常。
有什么方便的解决方案可以解决这个问题吗?由于显而易见的原因,我无法将使用数据源的所有网页标记为 [可序列化]。
EDIT 1:我不明白的东西。如果我将Dictionary 存储在Session 对象中(使用BinaryFormatter 与LosFormatter 代表ViewState),它就可以工作!我不知道怎么可能。也许BinaryFormatter 可以序列化任何类,即使是那些不是[serializable] 的类?
EDIT 2:重现问题的最小代码:
void test()
{
Test test = new Test();
string param1 = "parametertopass";
test.MyEvent += () => Console.WriteLine(param1);
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, test); //bang
}
}
[Serializable]
public class Test
{
public event Action MyEvent;
}
【问题讨论】:
-
“它有效!我不知道如何......”:会话数据保留在服务器端,在内存中。当您移动到 2 个以上的服务器时,它将开始中断。
标签: c# serialization delegates webforms viewstate