Как я могу красиво сократить этот код C #? - PullRequest
0 голосов
/ 03 марта 2019

Я хочу устранить дублирующийся код.Кто-нибудь может сделать этот код короче и лучше?

switch (now.site)
{

    case item.SITE.AMAZON:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"priceblock_ourprice\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"priceblock_dealprice\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    case item.SITE.ALI:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"j-sku-discount-price\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"j-sku-price\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    }
}

Ответы [ 3 ]

0 голосов
/ 03 марта 2019

Вот несколько рекомендаций относительно того, как вы можете украсить свой код -

  1. Объявить константы для всех запросов XPath.
  2. Объявить переменную вне оператора switch для захвата значения ценына основе вашего оператора case.
  3. Создайте функцию с одним оператором try catch, которая принимает 2 строки xPath и параметр out для Price и возвращает логическое значение, указывающее, был ли запрос успешным.
  4. Удалите трип-трик из-под каждого случая и вызовите эту функцию, передавая правильные строки xPath из набора констант.

    const string priceblock_ourprice = "//*[@id=\"priceblock_ourprice\"]";
    const string priceblock_dealprice = "//*[@id=\"priceblock_dealprice\"]";
    const string j_sku_discount_price = "//*[@id=\"j-sku-discount-price\"]";
    const string j_sku_price = "//*[@id=\"j-sku-price\"]";
    
    public void YourPrimaryFunction
    {  
        decimal price;  
        switch (now.site)  
        {  
            case item.SITE.AMAZON:  
                fetched = FetchPrice(priceblock_ourprice, priceblock_dealprice, out price);
                break;  
            case item.SITE.ALI:  
                fetched = FetchPrice(j_sku_discount_price, j_sku_price, out price);
                break;
        }
    }
    
    private bool FetchPrice(string xPathPrim, string xPathFallBack, decimal out price)
    {
        try
        {
            price = driver.FindElement(By.XPath(xPathPrim)).Text;
            return true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath(xPathFallBack)).Text;
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
    
0 голосов
/ 03 марта 2019

Похоже, вы действительно пытаетесь получить десятичное значение.Давайте воспользуемся этим предположением и создадим метод, который возвращает decimal? для обозначения успеха (то есть значения) или неудачи (то есть null).

public static class Ex
{
    public static decimal? FindDecimalMaybe(this IWebDriver driver, string path)
    {
        try
        {
            if (decimal.TryParse(driver.FindElement(By.XPath(path)).Text, out decimal result))
            {
                return result;
            }
        }
        catch { } // I hate this, but there doesn't seem to be a choice
        return null;
    }
}

Цель этого метода - скрыть неприятноеДело в том, что библиотека Selenium, по-видимому, кодирует исключение.

Я также создал ее как метод расширения, так что вызов driver.FindElement заменяется чем-то, что выглядит знакомым - driver.FindDecimalMaybe.

Теперь я использую тот же подход, что и Оливер со словарем:

private static Dictionary<string, string[]> __pricePaths = new Dictionary<string, string[]>
{
    { item.SITE.AMAZON, new [] { "//*[@id=\"priceblock_ourprice\"]", "//*[@id=\"priceblock_dealprice\"]" } },
    { item.SITE.ALI, new [] { "//*[@id=\"j-sku-discount-price\"]", "//*[@id=\"j-sku-price\"]" } },
};

Теперь тривиально вывести значения:

decimal? price =
    __pricePaths[now.site]
        .Select(path => driver.FindDecimalMaybe(path))
        .Where(x => x.HasValue)
        .FirstOrDefault();

Если переменная price имеетvalue затем success, но если это null, то вызов не был успешным.

0 голосов
/ 03 марта 2019

Вы можете создать словарь доступных строк пути.Я не знаю, что это за тип site.Я полагаю, string

private static Dictionary<string, string[]> pricePaths = new Dictionary<string, string[]> {
   [item.SITE.AMAZON] = new string[] { "//*[@id=\"priceblock_ourprice\"]",
                                       "//*[@id=\"priceblock_dealprice\"]" },
   [item.SITE.ALI] = new string[] { "//*[@id=\"j-sku-discount-price\"]",
                                    "//*[@id=\"j-sku-price\"]" },
};

С этим вы можете написать более общую логику.

bool fetched = false;
if (pricePaths.TryGetValue(now.site, out string[] paths)) {
    foreach (string path in paths) {
        try {
            price = driver.FindElement(By.XPath(path)).Text;
            fetched = true;
            break;
        } catch {
        }
    }
}

Это позволяет легко добавлять новые сайты.Сайты могут иметь произвольное количество альтернативных путей.

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