2013-05-25 50 views
3

首先,我有ComponentsWindowsFormsApplication5名稱下的兩個項目,我的解決方案的一部分(有更多,但這些都是無關緊要的)。我指的詞典都在Components,定義如下,沿與它們的屬性 - :字典屬性始終是空儘管字典被實例化

Dictionary<int, ButtonBase> RespMCQ, DispMCQ; //<Question Number, Checkbox/Radiobutton> 
Dictionary<int, List<ButtonBase>> RespMSQ, DispMSQ; 
public Dictionary<int, ButtonBase> MCQResp 
{ 
    get 
    { 
     return RespMCQ; 
    } 
    set 
    { 
     RespMCQ = value; 
    } 
} 
public Dictionary<int, List<ButtonBase>> MSQResponse 
{ 
    get 
    { 
     return RespMSQ; 
    } 
    set 
    { 
     RespMSQ = value; 
    } 
} 
public Dictionary<int, ButtonBase> MCQDisplay 
{ 
    get 
    { 
     return DispMCQ; 
    } 
    set 
    { 
     DispMCQ = value; 
    } 
} 
public Dictionary<int, List<ButtonBase>> MSQDisplay 
{ 
    get 
    { 
     return DispMSQ; 
    } 
    set 
    { 
     DispMSQ = value; 
    } 
} 

詞典都在QuestionDisplay.cs的構造,這是Components項目的一部分(實例化這是他們居住)。這顯示如下 - :

public QuestionDisplay() 
{ 
    InitializeComponent(); 
    RespMCQ = new Dictionary<int, ButtonBase>(); 
    DispMCQ = new Dictionary<int, ButtonBase>(); 
    RespMSQ = new Dictionary<int, List<ButtonBase>>(); 
    DispMSQ = new Dictionary<int, List<ButtonBase>>(); 
    .... 
} 

WindowsFormsApplication5Form1.cs(我沒有選擇這個名字,原諒我,如果這聽起來平淡無奇),我使用我所提到的特性。沒有命名空間問題,並且編譯正常進行。

期間Form1的,但是,當我把這些特性,他們拋出一個NullReferenceException說 - :

Object reference not set to an instance of an object. 

這些屬性的第一次出現是在一個名爲WorkFlowPanel(string S, QuestionContainerState obj)方法,這就是所謂的窗體加載的時間 - :

if (QuesTypes[i].Equals("MCQ")) 
{ 
    string text = ""; 
    for (int ansCount = 0; ansCount < questions[i].Options.Count(); ansCount++) 
    { 
     if (Convert.ToInt32(K.Key).Equals(ansCount + 1)) 
     { 
      text = questions[i].Options[ansCount]; 
      break; 
     } 
    } 
    questionDisplay1.MCQResp.Add(i, new CustomRadio { optionId = Convert.ToInt32(K.Key), Checked = true, Text = text }); //Using anonymous class 
} 
else if (QuesTypes[i].Equals("MSQ") || QuesTypes[i].Equals("Linked")) 
{ 
    var storeoptions = K.Key.Split(':'); 
    questionDisplay1.MSQResponse.Add(i, new List<ButtonBase>()); 
    for (int s = 0; s < storeoptions.Count(); s++) 
    { 
     questionDisplay1.MSQResponse[i].Add(new CustomChecks { optionId = Convert.ToInt32(storeoptions[s]), Checked = true, Text = questions[i].Options[Convert.ToInt32(storeoptions[s])] }); 
    } 
} 

令我驚訝的是,在調試時,我發現屬性始終是,儘管被實例化的字典空。現在這個問題有一些歷史,我將不得不深入研究,提供背景。

我之前正在與Could not find a type for a name. The type was System.Collections.Dictionary...錯誤發生在Form1.resx(我不記得整個錯誤)。顯然,詞典性質是系列化成二進制格式,編碼爲RESX文件的base64,如下 - :

<data name="MCQDisplay" mimetype="application/x-microsoft.net.object.binary.base64"> 
<value> 
     AAEAAAD/////AQAAAAAAAAAEAQAA.... 
</value> 
<data name="MSQDisplay" .....> 
.... 
.... 

我跟着一個解決方案,我#2發現,這跟我的代碼複製回成舊版本。這是自那時起我一直在應用的修復。我發現如果我刪除了這些條目(編譯器錯誤要求我這樣做),字典屬性將始終爲空。我覺得這與我目前的情況有關。恰巧在回拷操作期間,resx文件條目消失了。

從那時起,它從來沒有拋出此編譯器錯誤。我用盡了一切辦法,包括使用ResXResourceWriter再生的條目。這就像他們甚至不承認,和而不是錯誤,我在運行時告知,該字典屬性始終是空! IRC上的一個人建議,由於ButtonBase不可序列化,因此發生該錯誤的原因是,儘管Dictionary本身就是。那麼,我從來沒有要求編譯器序列化字典。我想知道爲什麼發生這種事。

如果有人能夠幫助我解決這個可怕的錯誤,我將非常感激。我的頭腦中也有這個模糊的解決方案,我不是將ButtonBase兒童存儲爲值,而是存儲具有鏡像文本,optionId和ButtonBase子項的屬性的屬性的類對象。但是,我認爲這是最後的手段。

EDIT_1:我不知道這是否是相關的,但我在Form1.Designer.cs發現這些條目 - :

this.questionDisplay1.MCQDisplay = ((System.Collections.Generic.Dictionary<int, System.Windows.Forms.ButtonBase>)(resources.GetObject("questionDisplay1.MCQDisplay"))); 
this.questionDisplay1.MCQResp = ((System.Collections.Generic.Dictionary<int, System.Windows.Forms.ButtonBase>)(resources.GetObject("questionDisplay1.MCQResp"))); 
this.questionDisplay1.MSQDisplay = ((System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<System.Windows.Forms.ButtonBase>>)(resources.GetObject("questionDisplay1.MSQDisplay"))); 
this.questionDisplay1.MSQResponse = ((System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<System.Windows.Forms.ButtonBase>>)(resources.GetObject("questionDisplay1.MSQResponse"))); 

我一定要刪除這些或修改它們以某種方式?我覺得這些與馬修的答案有某種關係。

EDIT_2:我管理,由以下來解決這個問題 - :

  1. 馬修·沃森的非系列化修復 - 櫃面編譯器試圖再次序列化字典屬性。
  2. 我註釋了Form1.Designer.cs中的條目,這些我在上面提到過。

我接受馬修的答案,因爲我覺得非序列化修復是相關的。

+0

如果您在組件類中顯示構造函數的代碼會很有幫助,您如何實例化此類的實例以及如何嘗試訪問字典 – Steve

+0

@Steve:直接添加! – PritishC

回答

1

這些屬性是來自FormUserControlControl派生類的公共和成員?

如果是這樣,表單設計器可能會嘗試將這些屬性序列化到表單的Designer.cs文件中。 (事實上​​,從你說的話,它完全可能

要停止這種情況發生,你可以使用DesignerSerializationVisibilityAttribute,以防止它,例如:

[ 
    Browsable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
] 

public MyType MyPropertyWhichMustNotBeSerialized 
{ 
    get; 
    set; 
} 

你必須編輯儘管它已經放入「.Designer.cs」文件中的任何不良內容 - 添加此屬性可能不會使其自動消失。

如果,如果你需要添加這個屬性你沒有定期檢查,我想你可能想通過進去直接或間接從Control派生的任何類都的公共屬性,並在必要時添加此屬性。


對於問題將空引用;有可能FormLoad()被稱爲InitialiseComponent()的呼叫的副作用嗎?這會導致一個空引用錯誤。

爲了最安全起見,您應該爲您的屬性使用後備字段而不是自動屬性。

然後,而不是初始化在構造函數中的字段,初始化它們就在你申報的領域,如:

private Dictionary<int, ButtonBase>  respMCQ = new Dictionary<int, ButtonBase>(); 
private Dictionary<int, ButtonBase>  dispMCQ = new Dictionary<int, ButtonBase>(); 
private Dictionary<int, List<ButtonBase>> respMSQ = new Dictionary<int, List<ButtonBase>>(); 
private Dictionary<int, List<ButtonBase>> dispMSQ = new Dictionary<int, List<ButtonBase>>(); 

,這樣可以保證任何構造函數被調用之前被初始化的方式。

+0

屬性確實是公共的,但它們所在的類是從'UserControl'派生的。不過,我仍然會嘗試解決您的問題。首先清理resx文件中的條目。 – PritishC

+0

@UncleDolan我也應該說'UserControl' - 這也受到影響 –

+0

試過這個,但沒有什麼區別。 nullref異常仍然在被拋出,它發生在我嘗試向'questionDisplay1.MSQResponse'中添加條目的行中。 – PritishC