2012-08-28 41 views
6

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; 
    } 
} 

这夏精是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); 

它不活像Ks了,我得到这个错误:

类型System.Web.UI.Page在程序集'...'中没有标记为 可序列化。

发生了什么事:

  1. 串行器检查字典。它认为它包含由于委托类中定义一个匿名委托(拉姆达这里)
  2. ,它尝试序列全班,在这种情况下System.Web.UI.Page
  3. 该类没有标记为序列化
  4. 它抛出,因为3

异常是否有方便的解决方案来解决这个?由于显而易见的原因,我无法将所有使用数据源的网页标记为[serializable]。


编辑1:东西我不明白。如果我将Dictionary存储在Session对象中(它使用BinaryFormatterLosFormatter代替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; 
} 
+0

“它的工作原理!我不知道如何...”:会话数据仍然是服务器端,内存中。当您移动到2台服务器时,它将开始中断。 –

+0

thx的信息 – tigrou

回答

0

我发现了一个解决方案,这是我如何做的:

我修改这样的字典定义:

Dictionary<string, KeyValuePair<Func<T, object[], bool>, object[]>> 

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

现在过滤器可以这样设置:

int userId = int.Parse(DdlUsers.SelectedValue); 
DataSource.Filters.Add("userid", (u, args) => u.UserID == (int)args[0], userId); 

它的工作原理,因为现在拍摄的变量没有更多的部分代表,而是作为委托的参数给出。

4

好问题。我可以确认你的诊断(用一个小小的更正:基础架构试图序列化可能包含对你的页面的引用的闭包类)。

您可以定义自己的封闭类,并有连载:

[Serializable] class Closure { int userId; bool Filter(User u) { ... } }; 

那是不是方便,虽然。

我建议你使用不同的模式:不要序列化“代码”。通过序列化过滤器中使用的数据:

class FilterSettings { int userId; int someOtherFiler; string sortOrder; ... } 

虽然我不能指出确切的原因,我宁愿我凭直觉知道这是一个更好的办法。

+0

谢谢你的回答。我不确定第二个主张会如何工作。谁将实例化并保存FilterSettings类的实例?如果它的页面,序列化程序也不会有任何风险到达页面?您能否提供更多关于如何使用此解决方案的代码? – tigrou

+0

存储您精确控制的字段将永远不会引用该页面。序列化程序无法从Closure或FilterSettings开始到达页面。 – usr

+0

即使有你的建议,我仍然无法使它工作。我在问题的底部添加了一个代码示例,它将重现此问题。你能看看并给我提示吗? – tigrou

相关问题