如何才能漂亮地缩短此C#代码?

时间:2019-03-02 22:05:45

标签: c# oop refactoring

我想消除一些重复的代码。任何人都可以使这段代码更短,更好吗?

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 :(得分:7)

您可以创建可用路径字符串的字典。我不知道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 {
        }
    }
}

它使您可以轻松添加新站点。这些站点可以具有任意数量的备用路径。

答案 1 :(得分:0)

看来您实际上是在尝试获取十进制值。让我们使用此假设,并创建一个返回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

现在,我使用与Oliver相同的方法来制作字典:

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变量具有值,则成功,但是如果变量null,则调用未成功。

答案 2 :(得分:-1)

有关如何美化代码的一些建议-

  1. 声明所有XPath查询的常量。
  2. 在switch语句外声明一个变量,以根据case语句捕获价格值。
  3. 使用一个try catch语句创建一个函数,该语句接受2个xPath字符串和一个Price的out参数,并返回一个布尔值以指示查询是否成功。
  4. 从每种情况下删除try捕获,然后调用该函数以从常量集中传递正确的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;
            }
        }
    }