我正在努力将以下嵌套循环转换为具有更易读的LINQ语句的条件。
IEnumerable<PropertyInfo> testClassPageObjects = FindPageObjects();
T newControl = default(T);
Parallel.ForEach(testClassPageObjects, (pageObject,state) =>
{
Type pageObjectType = pageObject.PropertyType;
var pageObjectControls = pageObjectType.GetFields();
foreach (var control in pageObjectControls.Where(control => control.FieldType == typeof(T)))
{
if (control.Name == fieldNameNoSpaces)
{
var findsByAttribute = (FindsByAttribute) control.GetCustomAttribute(typeof(FindsByAttribute));
newControl = (T) control
.FieldType
.GetConstructor(new[] {typeof(IWebDriver), typeof(By)})
.Invoke(new object[] {driver, findsByAttribute.Locator});
state.Break();
}
}
});
如果可能的话,我想在LINQ语句中使用if语句之前的所有内容。该陈述应该返回第一场比赛。在这种情况下,使用Parallel.ForEach和foreach不需要相关。
非常感谢,
答案 0 :(得分:1)
认为它看起来像这样。不确定这是否更诚实。
T control = FindPageObjects
.SelectMany
(
pageObject =>
pageObject.PropertyType.GetFields()
)
.OfType<T>()
.Where
(
control =>
control.FieldType == typeof(T) &&
control.Name == fieldNameNoSpaces
)
.Select
(
selectedControl =>
selectedControl.FieldType
.GetConstructor(new[] { typeof(IWebDriver), typeof(By)})
.Invoke
(
new object[]
{
driver,
((FindsByAttribute)(selectedControl.GetCustomAttribute(typeof(FindsByAttribute)))).Locator
}
)
)
.OfType<T>()
.FirstOrDefault();
说明:
SelectMany 允许您迭代集合中的集合(页面对象中的控件)
OfType 确保您只查看T类型的控件,并且无需在以后进行投射。
其中检查字段类型和名称。
选择使用反射根据控件的FieldType实例化新T。
OfType 是第二次将构造函数调用的结果强制转换为T。
FirstOrDefault 意味着LINQ将为它找到的第一条记录运行它,如果它找不到它,它只会返回null。这与原始代码中的Break
相对应。
顺便说一句,如果你想要并行,你可以简单地添加AsParallel,虽然我不确定会有多大改进。