tig*_*rou 6 c# viewstate serialization delegates webforms
在a中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;
}
}
Run Code Online (Sandbox Code Playgroud)
这个webcontrol是一个DataSource
,我创建了这个属性,因为我希望有可能轻松过滤数据,例如:
//in page load
DataSource.Filters.Add("userid", u => u.UserID == 8);
Run Code Online (Sandbox Code Playgroud)
但是,如果我将代码更改为:
//in page load
int userId = int.Parse(DdlUsers.SelectedValue);
DataSource.Filters.Add("userid", u => u.UserID == userId);
Run Code Online (Sandbox Code Playgroud)
它不再起作用,我收到此错误:
程序集"..."中的System.Web.UI.Page类型未标记为可序列化.
发生了什么 :
有没有方便的解决方案来解决这个问题?由于显而易见的原因,我无法将所有使用数据源的网页标记为[可序列化].
编辑1:我不明白的东西.如果我存储Dictionary
在Session
对象中(使用BinaryFormatter
vs LosFormatter
for ViewState
),它就可以了!我不知道怎么可能.也许BinaryFormatter
可以序列化任何一个类,即使这些不是[serializable]
?
编辑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;
}
Run Code Online (Sandbox Code Playgroud)
我找到了一个解决方案,这就是我的做法:
我像这样修改了字典定义:
Dictionary<string, KeyValuePair<Func<T, object[], bool>, object[]>>
Run Code Online (Sandbox Code Playgroud)
(KeyValuePair
是可序列化的,就像Dictionary
)
并创建了一个新Add()
函数:
public void Add(string key, Func<T, object[], bool> filter, params object[] args)
{
this.Add(key, new KeyValuePair<Func<T, object[], bool>, object[]>
(filter, args));
}
Run Code Online (Sandbox Code Playgroud)
现在过滤器可以这样设置:
int userId = int.Parse(DdlUsers.SelectedValue);
DataSource.Filters.Add("userid", (u, args) => u.UserID == (int)args[0], userId);
Run Code Online (Sandbox Code Playgroud)
它有效,因为现在捕获的变量不再是委托的一部分,而是作为委托的参数给出。