我可以使用LINQ来获取某种类型的所有组件吗?

时间:2012-11-06 00:42:19

标签: c# linq clr

我对C#相当新,并且遇到了一些问题,我确信使用LINQ有一个很好的解决方案。

背景 我继承了一个使用CrystalReports的项目,报告本身都有以统一方式与它们相关联的查看器形式[包含组件/控件](我相当确定它们是机器生成的) ,其中一个是ReportClass的后代,它包含一个数据库属性。数据库属性是唯一的东西,它区分出现在所有这些类中的方法(Log_On_Database)。我想要做的是创建一个公共基类,搜索ReportClass的表单并使用它来填充其本地数据库变量w /属性中的值,以便我可以在单个中实现Log_On_Database位置。

问题: 如何使用LINQ来获取属于某个表单的所有components(不是[just]控件),并为那些 控件(因此可以拥有自己的控件)递归?

注意:List中获得结果会很棒,因为我可以测试长度为0(出现严重错误),1(预期)或更多(然后我可以在那些奇怪的情况下做我需要做的事情) - 即使这是所有生成的代码,我也不相信而不是已经以极其痛苦的方式进行了修改。

2 个答案:

答案 0 :(得分: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语句中会很好。

答案 1 :(得分:0)

使用linq,您无法执行递归查询,因此GetAll应保持原样。

但是你可以这样做:

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