如何在WinForm中设置非静态委托?

时间:2014-10-22 12:11:30

标签: c# winforms visual-studio-2010 serialization

我写了一个TextBox来检查其文本的有效性。检查文本的方法由呼叫者提供为System.Func<string, bool>。简化代码如下所示:

public class ValidTextBox : System.Windows.Forms.TextBox
{
    public System.Func<string, bool> IsValid { get; set; }
}

我成功地使用了几件事,但后来我尝试提供非静态方法。代码编译得很好,但每当我尝试将它从工具箱拖到窗体中时,Visual Studio的设计器都会抛出一个冗长的异常(见下文)。

public class SpecialTextBox : ValidTextBox
{
    public SpecialTextBox()
    {
        base.IsValid = s => true; // works
        base.IsValid = StaticReturnTrue; // works
        base.IsValid = s => StaticReturnTrue(s); // works
        base.IsValid = this.ReturnTrue; // doesn't work
        base.IsValid = s => this.ReturnTrue(s); // doesn't work
    }

    private static bool StaticReturnTrue(string s)
    {
        return true;
    }

    private bool ReturnTrue(string s)
    {
        return true;
    }
}

我无法复制并粘贴MessageBox的文本,请原谅错别字。语言是德语:

  

Fehler beim Erstellen der Komponente SpecialTextBox。 Die Fehlermeldung:   System.Runtime.Serialization.SerializationException:Der Typ&#34; GuiTest.SpecialTextBox&#34;在Assembly&#34; GuiTest,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#34; ist nicht als serialisierbar gekennzeichnet   bei System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
  bei System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type,StreamingContent content)
  bei System.Runtime.Serialization.FormatterServices.Binary.WriteObjectInfo.InitMemberInfo()
  bei System.Runtime.Serialization.FormatterServices.Binary.WriteObjectInfo.InitSerialze([...])   bei System.Runtime.Serialization.FormatterServices.Binary.ObjectWriter.Write([...])

如果我将SpecialTextBox标记为[System.Serializable],则设计师会抱怨ValidTextBox未标记为可序列化。如果我将ValidTextBox标记为[System.Serializable],设计师会抱怨System.Windows.Forms.TextBox未标记为可序列化,我无法更改。

为什么设计师会例外?

如何在运行时提供非静态方法?

1 个答案:

答案 0 :(得分:3)

它尝试序列化属性值,因为它具有非null值。这无法达到目的,C#编译器为实现lambda(委托的目标对象的类型)而生成的隐藏类是不可序列化的。当需要捕获状态时,这是一个问题,例如正确调用ReturnTrue()方法所需的 this 引用。

修复很简单,您不需要序列化,因为您始终在运行时初始化它。所以使用属性来阻止它:

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Func<string, bool> IsValid { get; set; }