2012-11-06 128 views
2

我對C#相當陌生,並且遇到了一些問題,我確定使用LINQ有一個很好的解決方案。我可以使用LINQ獲取某種類型的所有組件嗎?

背景: 有我繼承了使用水晶報表項目,報告本身都有觀衆的表單[含組件/控件]他們以統一的方式有關(我確信他們是機生成),其中之一是來自ReportClass的組件,後者包含數據庫屬性。數據庫屬性是只有區分出現在所有這些類中的方法(Log_On_Database)。我想要做的是創建一個公共基類,該表搜索表格ReportClass並使用它來填充其本地數據庫變量w /來自屬性的值,以便我可以在單個位置實現Log_On_Database

問: 一個人如何使用LINQ來獲取所有components(不[僅僅]控件)屬於一種形式,遞歸那些控制(因此可以有自己的)?

注:獲得的結果在List將是巨大的,因爲我可以再試驗的長度爲0(出事了可怕的錯誤),1(預期),或更多(然後我可以做什麼,我需要在那些奇怪的情況下) - 即使這是所有生成的代碼,我不相信它而不是已經以可怕的痛苦方式進行了修改。

回答

1

到目前爲止,我已經得到了

// Get all controls of a certain type: 
    // http://stackoverflow.com/questions/3419159/how-to-get-all-child-controls-of-a-winform-of-a-specific-type-button-textbox 
    public IEnumerable<Control> GetAll(Control control, Type type) 
    { 
     var controls = control.Controls.Cast<Control>(); 

     return controls.SelectMany(ctrl => GetAll(ctrl, type)) 
            .Concat(controls) 
            .Where(c => c.GetType() == type); 
    } 

    protected ComponentCollection get_components(Component c) 
    { 
     Type parent = c.GetType(); 
     FieldInfo fieldInfo = parent.GetField("components", BindingFlags.Instance | BindingFlags.NonPublic); 
     IContainer fieldData = (IContainer)fieldInfo.GetValue(components); 

     return fieldData.Components; 
    } 

    protected void Log_On_Database() 
    { 
     // ReportClass decends from ReportDocument, which has the Database property we're interested in 
     // this method grabs up any ReportDocument and decended objects. There should be only one. 
     List<ReportDocument> reports = new List<ReportDocument>(); 

     // The list 'ctrls' contains all the Controls of 'this' form. 
     List<Control> ctrls = GetAll(this, typeof(Control)).ToList(); 

     // Now we add all the components from all the controls which are ReportDocuments to the "reports" list. 
     foreach (Control c in ctrls) 
      foreach(Component x in get_components(c)) 
      { 
       if (x is ReportDocument) 
        reports.Add((ReportDocument)x); 
      } 

     switch (reports.Count) 
     { 
      case 0: 
       MessageBox.Show("No report document found."); 
       break; 
      case 1: 
       Log_On_Database(((ReportDocument)reports[0]).Database); 
       break; 
      default: 
       MessageBox.Show("Too many report documents found."); 
       break; 
     } // end switch 

    } // end Log_On_Database 

這將是很好得到這一切在一個LINQ聲明。

+0

請將這對你的問題。 –

0

隨着linq你不能做遞歸查詢,所以GetAll應該保持原樣。

但你可以這樣做:

var reports = GetAll(this, typeof(Control)) 
      .SelectMany(c => get_components(c)) 
      .OfType<ReportDocument>() 
      .ToList(); 
相關問題