我对C#
相当新,并且遇到了一些问题,我确信使用LINQ有一个很好的解决方案。
背景
我继承了一个使用CrystalReports的项目,报告本身都有以统一方式与它们相关联的查看器形式[包含组件/控件](我相当确定它们是机器生成的) ,其中一个是ReportClass
的后代,它包含一个数据库属性。数据库属性是唯一的东西,它区分出现在所有这些类中的方法(Log_On_Database
)。我想要做的是创建一个公共基类,搜索ReportClass
的表单并使用它来填充其本地数据库变量w /属性中的值,以便我可以在单个中实现Log_On_Database
位置。
问题:
如何使用LINQ来获取属于某个表单的所有components
(不是[just]控件),并为那些 控件(因此可以拥有自己的控件)递归?
注意:在List
中获得结果会很棒,因为我可以测试长度为0(出现严重错误),1(预期)或更多(然后我可以在那些奇怪的情况下做我需要做的事情) - 即使这是所有生成的代码,我也不相信而不是已经以极其痛苦的方式进行了修改。
答案 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();