2009-10-09 79 views
2

基於這個答案Get the subdomain from a URL,我試圖使用code.google.com/p/domainname-parser/將使用Public Suffix從publicsuffix.org列出來獲取管理我的Cookie收集的子域和域。將Linq轉換爲正常的C#.NET 2.0,用於使用publicsuffix.org的域名解析器代碼

在當前時刻,Domainname-parser是我在互聯網上找到的唯一.NET代碼,它實現了publicsuffix.org的列表。

爲了使用域名解析器我想做出改變的源代碼,以便它能夠:

  1. 使用.NET 2.0中
  2. 接受Uri對象來解析主機到子域名,域名和頂級域名。
  3. 如果更改LastModified,將自動使用WebRequest和WebResponse從publicsuffix.org下載最新列表。

因此,它會變得更加有用並且始終更新。 (2)和(3)不會成爲問題,但(1)現在是我的焦點。

當前的域名解析器是v1.0,爲了使用在代碼中使用Linq的.NET 3.5而構建。爲了使它與.NET 2.0兼容,我需要將Linq代碼轉換爲非Linq,這使我瞭解公共後綴列表規則。這是普通,通配符和例外規則。但是我不瞭解Linq,以及它如何轉換回正常的方式。

轉換工具可能是有用的,但更好的是我審查並逐行修改它。

現在我的問題是我該如何轉換它?從FindMatchingTLDRule方法如代碼在DOMAINNAMES類:

// Try to match an wildcard rule: 
var wildcardresults = from test in TLDRulesCache.Instance.TLDRuleList 
         where 
         test.Name.Equals(checkAgainst, StringComparison.InvariantCultureIgnoreCase) 
         && 
         test.Type == TLDRule.RuleType.Wildcard 
         select 
         test; 

而且這樣的:

 var results = from match in ruleMatches 
         orderby match.Name.Length descending 
         select match; 

什麼是簡單的引導線遵循? 或任何免費工具將上面的這一句話轉換爲.NET 2.0中的正常C#代碼。

我相信不涉及數據庫,就像他們處理集合的方式一樣。

我也試圖聯繫域名解析器所有者來改進代碼並幫助我解決這個問題。

感謝

CallMeLaNN

回答

1

感謝Jon Skeet對我真的很有幫助。它工作得很好,所有UnitTest都成功通過。

在這裏,我想分享的答案,任何人要使用域名解析器在.NET 2.0

1更改此代碼(DomainName.cs)

  // Try to match an exception rule: 
      var exceptionresults = from test in TLDRulesCache.Instance.TLDRuleList 
            where 
            test.Name.Equals(checkAgainst, StringComparison.InvariantCultureIgnoreCase) 
            && 
            test.Type == TLDRule.RuleType.Exception 
            select 
            test; 

      // Try to match an wildcard rule: 
      var wildcardresults = from test in TLDRulesCache.Instance.TLDRuleList 
            where 
            test.Name.Equals(checkAgainst, StringComparison.InvariantCultureIgnoreCase) 
            && 
            test.Type == TLDRule.RuleType.Wildcard 
            select 
            test; 

      // Try to match a normal rule: 
      var normalresults = from test in TLDRulesCache.Instance.TLDRuleList 
           where 
            test.Name.Equals(checkAgainst, StringComparison.InvariantCultureIgnoreCase) 
            && 
            test.Type == TLDRule.RuleType.Normal 
           select 
            test; 

到這一點:

List<TLDRule> exceptionresults = MatchRule(TLDRulesCache.Instance.TLDRuleList, checkAgainst, TLDRule.RuleType.Exception); 
List<TLDRule> wildcardresults = MatchRule(TLDRulesCache.Instance.TLDRuleList, checkAgainst, TLDRule.RuleType.Wildcard); 
List<TLDRule> normalresults = MatchRule(TLDRulesCache.Instance.TLDRuleList, checkAgainst, TLDRule.RuleType.Normal); 

    private static List<TLDRule> MatchRule(List<TLDRule> rules, string checkAgainst, TLDRule.RuleType ruleType) 
    { 
     List<TLDRule> matchedResult = new List<TLDRule>(); 
     foreach (TLDRule rule in rules) 
     { 
      if (rule.Name.Equals(checkAgainst, StringComparison.InvariantCultureIgnoreCase) 
       && rule.Type == ruleType) 
      { 
       matchedResult.Add(rule); 
      } 
     } 
     return matchedResult; 
    } 

2更改如下:

 // Sort our matches list (longest rule wins, according to : 
     var results = from match in ruleMatches 
         orderby match.Name.Length descending 
         select match; 

     // Take the top result (our primary match): 
     TLDRule primaryMatch = results.Take(1).SingleOrDefault(); 

這個

 TLDRule primaryMatch = null; 
     if (ruleMatches.Count > 0) 
     { 
      // match2 CompareTo match1 (reverse order) to make the descending 
      ruleMatches.Sort(delegate(TLDRule match1, TLDRule match2) { return match2.Name.Length.CompareTo(match1.Name.Length); }); 
      primaryMatch = ruleMatches[0]; 
     } 

3改變這種(TLDRulesCache.cs)

  IEnumerable<TLDRule> lstTLDRules = from ruleString in lstTLDRuleStrings 
               where 
               !ruleString.StartsWith("//", StringComparison.InvariantCultureIgnoreCase) 
               && 
               !(ruleString.Trim().Length == 0) 
               select new TLDRule(ruleString); 

這個

​​

有些人就像是一個小東西:

List<string> lstDomainParts = domainString.Split('.').ToList<string>(); 

更改爲:

List<string> lstDomainParts = new List<string>(domainString.Split('.')); 

,並像

「VAR exceptionresults」 將使用exceptionresults.ToList()來獲取列表中刪除.ToList()。由於「var exceptionresults」更改爲「List exceptionresults」,因此應移除.ToList()。

CallMeLaNN

1

好,響應意見,這裏是返回一個列表中的版本。

public List<TLDRule> MatchWildcards(IEnumerable<TLDRule> rules, 
            string checkAgainst) 
{ 
    List<TLDRule> ret = new List<TLDRule>(); 
    foreach (TLDRule rule in rules) 
    { 
     if (rule.Name.Equals(checkAgainst, 
          StringComparison.InvariantCultureIgnoreCase) 
      && rule.Type == TLDRule.RuleType.Wildcard) 
     { 
      ret.Add(rule); 
     } 
    } 
    return ret; 
} 

Then: 

List<TLDRule> wildcardresults = MatchWildcards(
    TLDRulesCache.Instance.TLDRuleList, checkAgainst); 

但是,如果你將大量的代碼(如果你真的把它轉換 - 見下文),你應該瞭解LINQ。你最終肯定會使用它,如果你明白它是如何工作的,你將能夠更好地瞭解如何進行轉換。最新的C#書籍涵蓋了LINQ;如果你有我自己的書(深度C#),那麼第8-11章將涵蓋你需要知道的LINQ to Objects的一切。

如果你能使用VS2008只是目標另一種選擇 .NET 2.0是使用LINQBridge這是LINQ到了.NET 2.0的對象重新實現......它現在open source :)

+0

感謝您的快速響應。它似乎工作。 現在我想將IEnumerable 更改爲列表,以便我可以使用like wildcardresults.Count。 所以新的語句變成:List exceptionresults =(List )MatchExceptions(TLDRulesCache.Instance.TLDRuleList,checkAgainst); 因爲我無法更改方法IEnumerable MatchExceptions()到列表 MatchExceptions()因爲使用關鍵字「yield」。 我認爲你的意思是類型。 我沒有看到任何改變checkAgainst值的代碼。 – CallMeLaNN 2009-10-09 07:43:43

+0

好的,我會編輯該方法。 – 2009-10-09 07:48:34

+0

Oic,即收益率意味着。 TQVM。 只是我編輯的另一個代碼。我混淆了「orderby」。不同的情況。我不知道如何在if語句中比較以測試match.Name.Length以與之前的匹配對象進行比較。 幾乎完成。 – CallMeLaNN 2009-10-09 07:56:34