Вы можете использовать для этого генератор.
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/