Повторить запрос linq несколько раз - PullRequest
0 голосов
/ 02 августа 2020

Этот вопрос связан с предыдущим вопросом Запрос Linq выбирает значения из первой строки только в таблице

Я пытаюсь заставить этот код работать. Я намерен добавить видимые элементы из веб-таблицы в объект с помощью запроса Linq. Веб-таблица загружается динамически, поэтому при прокрутке она загружается элементами, а другие элементы выгружаются одновременно. Прокрутка вниз сразу после загрузки страницы невозможна.

У меня есть несколько вопросов:

  1. Можно ли выполнить запрос Linq таким образом (добавить видимые элементы, прокрутить, добавить видимые элементы и т. Д. c.)
  2. Как преобразовать DataHereH в список DataHere?

Вот мой текущий код:

    public static IEnumerable<UserTableRow> AddItemsToList(IWebDriver driver)
    {

        IReadOnlyCollection<IWebElement> rows = new List<IWebElement>();

        object DataHereH;

        driver.FindElement(By.XPath("//*[@id=\"users_table\"]/div[5]/div/div[1]")).Click();

        for (int i = 0; i < 4; i++)
        {
            rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));

            // This part will get our first visible items in table to list, after page load 
            DataHereH = from row in rows
                        select new UserTableRow(row);

            Actions actions = new Actions(driver);
            actions.SendKeys(Keys.PageDown).Build().Perform();
        }

        List<UserTableRow> noDupes = DataHere.Distinct().ToList();

        return noDupes;
    }

Вот параметры:

   public class UserTableRow
    {
        private readonly IWebElement row;

        public string Username => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
        public string Firstname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l1 r1')]")).Text;
        public string Lastname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l2 r2')]")).Text;
        public string Type => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l3 r3')]")).Text;
        public string Crew => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l4 r4')]")).Text;
        public string JobTitle => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l5 r5')]")).Text;
        public string DefaultPrice => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l6 r6')]")).Text;
        public string Future => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l7 r7')]")).Text;
        public string Language => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l8 r8')]")).Text;

        public override string ToString()
        {
            return "SharePrice: " + Username.ToString() + ": " + Firstname.ToString();
        }

        public UserTableRow(IWebElement row)
        {
            try
            {
                this.row = row;
            }
            catch (Exception)
            {

                throw;
            }
        }
    }

1 Ответ

3 голосов
/ 07 августа 2020

Вы можете использовать для этого генератор.

public static IEnumerable<UserTableRow> AddItemsToList(IWebDriver driver)
{
    var uniqueData = new HashSet<UserTableRow>();
    var actions = new Actions(driver);

    driver.FindElement(By.XPath("//*[@id=\"users_table\"]/div[5]/div/div[1]")).Click();
    for (int i = 0; i < 4; i++) 
    {
        var latestElements = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));
        foreach (var element in latestElements)
        {
            var row = new UserTableRow(element);
            var isUnique = uniqueData.Add(row);
            if (isUnique) yield return row;
        }
        actions.SendKeys(Keys.PageDown).Build().Perform();
    }
}

Но имейте в виду, , как в этом случае, так и в случае Linq Distinct вам необходимо предоставить объект, который использует равенство значений.

В настоящее время ваш класс UserTableRow использует ссылочное равенство, поэтому вы будете получать дубликаты.

Чтобы смягчить это, вы можете сделать одно из следующих:

Пример

Если вы скопируете базовый класс из следующего руководства от Microsoft https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects

public abstract class ValueObject
{
    protected static bool EqualOperator(ValueObject left, ValueObject right)
    {
        if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
        {
            return false;
        }
        return ReferenceEquals(left, null) || left.Equals(right);
    }

    protected static bool NotEqualOperator(ValueObject left, ValueObject right)
    {
        return !(EqualOperator(left, right));
    }

    protected abstract IEnumerable<object> GetAtomicValues();

    public override bool Equals(object obj)
    {
        if (obj == null || obj.GetType() != GetType())
        {
            return false;
        }

        ValueObject other = (ValueObject)obj;
        IEnumerator<object> thisValues = GetAtomicValues().GetEnumerator();
        IEnumerator<object> otherValues = other.GetAtomicValues().GetEnumerator();
        while (thisValues.MoveNext() && otherValues.MoveNext())
        {
            if (ReferenceEquals(thisValues.Current, null) ^
                ReferenceEquals(otherValues.Current, null))
            {
                return false;
            }

            if (thisValues.Current != null &&
                !thisValues.Current.Equals(otherValues.Current))
            {
                return false;
            }
        }
        return !thisValues.MoveNext() && !otherValues.MoveNext();
    }

    public override int GetHashCode()
    {
        return GetAtomicValues()
         .Select(x => x != null ? x.GetHashCode() : 0)
         .Aggregate((x, y) => x ^ y);
    }
    // Other utility methods
}

Тогда вы можете переопределить UserTableRow следующим образом:

public class UserTableRow : ValueObject
{
    public string Username { get; private set; }
    public string Firstname{ get; private set; }
    public string Lastname { get; private set; }
    public string Type { get; private set; }
    public string Crew { get; private set; }
    public string JobTitle { get; private set; }
    public string DefaultPrice { get; private set; }
    public string Future { get; private set; }
    public string Language { get; private set; }

    public UserTableRow(IWebElement row)
    {
        Username = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
        Firstname = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l1 r1')]")).Text;
        LastName = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l2 r2')]")).Text;
        Type = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l3 r3')]")).Text;
        Crew = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l4 r4')]")).Text;
        JobTitle = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l5 r5')]")).Text;
        DefaultPrice = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l6 r6')]")).Text;
        Future = row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l7 r7')]")).Text;
        Language =row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l8 r8')]")).Text;
    }
    
    protected override IEnumerable<object> GetAtomicValues()
    {
        yield return Username;
        yield return Firstname;
        yield return LastName;
        yield return Type;
        yield return Crew;
        yield return JobTitle;
        yield return DefaultPrice;
        yield return Future;
        yield return Language;
    }
}

Это имеет то преимущество, что реализует равенство значений, поэтому вы сможете использовать хэш-набор для удаления дубликатов. Но у него есть недостаток, заключающийся в отсутствии возможности взаимодействия с элементами, так как это обеспечит изображение дома во время строительства. записей https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...