将嵌套循环转换为LINQ的问题

时间:2017-09-26 23:19:13

标签: c# linq reflection

我正在努力将以下嵌套循环转换为具有更易读的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不需要相关。

非常感谢,

1 个答案:

答案 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,虽然我不确定会有多大改进。