代码之家  ›  专栏  ›  技术社区  ›  CallMeLaNN

将使用publicSuffix.org的域名解析程序代码的downgrade linq转换为normal c.net 2.0

  •  2
  • CallMeLaNN  · 技术社区  · 16 年前

    基于这个答案 Get the subdomain from a URL ,我正在尝试使用code.google.com/p/domainname-parser/,它将使用public suffix.org中的公共后缀列表来获取用于管理我的cookie集合的子域和域。

    目前,域名解析器是我在Internet上找到的唯一一个实现publicSuffix.org列表的.NET代码。

    为了使用域名解析器,我想对源代码进行更改,以便它能够:

    1. 在.NET 2中使用
    2. 接受uri对象,将主机解析为子域、域和tld。
    3. 如果lastmodified被更改,将使用webrequest和webresponse从publicsuffix.org自动下载最新的列表。

    因此,它将变得更加可用并始终更新。(2)和(3)不是问题,但(1)是我现在的重点。

    当前的域名解析程序是v1.0,构建为使用代码中使用LINQ的.NET 3.5。为了使它与.NET 2.0兼容,我需要将LINQ代码转换为非LINQ,这使我能够理解公共后缀列表规则。这是正常的、通配符和异常规则。但是,我不知道LINQ以及如何将其转换回正常的方式。

    转换器工具可能很有用,但更好的是我一行一行地检查和修改它。

    现在我的问题是如何转换它?例如,来自域名类中findmatchingtlddrule方法的代码:

    //  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代码?

    我相信没有涉及到数据库,只是以他们处理收集的方式。

    我还试图联系域名解析器所有者来改进代码并帮助我解决这个问题。

    谢谢

    卡勒梅林

    2 回复  |  直到 8 年前
        1
  •  1
  •   Jon Skeet    16 年前

    好的,作为对评论的回应,这里有一个返回列表的版本。

    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 这是对.NET 2.0的linq to对象的重新实现…现在 open source :)

        2
  •  1
  •   CallMeLaNN    16 年前

    多亏了乔恩·斯基特,这真的对我有帮助。它工作得很好,所有的单元测试都通过了。

    在这里,我想与任何想在.NET 2.0中使用域名解析程序的人分享答案。

    1更改此代码(域名.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<TLDRule> lstTLDRules = ListTLDRule(lstTLDRuleStrings);
    
        private static List<TLDRule> ListTLDRule(List<string> lstTLDRuleStrings)
        {
            List<TLDRule> lstTLDRule = new List<TLDRule>();
            foreach (string ruleString in lstTLDRuleStrings)
            {
                if (!ruleString.StartsWith("//", StringComparison.InvariantCultureIgnoreCase)
                    &&
                    !(ruleString.Trim().Length == 0))
                {
                    lstTLDRule.Add(new TLDRule(ruleString));
                }
            }
            return lstTLDRule;
        }
    

    还有一些是小事情,比如:

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

    更改为:

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

    并删除.tolist()中的

    “var exceptionresults”将使用exceptionresults.to list()获取列表。由于“var exceptionresults”更改为“list exceptionresults”.to list()应被删除。

    卡勒梅林