2

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

目前,域名解析器是我在互联网上找到的唯一一个实现来自 publicsuffix.org 的列表的 .NET 代码。

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

  1. 在 .NET 2.0 中使用
  2. 接受 Uri 对象将主机解析为子域、域和 TLD。
  3. 如果 LastModified 更改,将使用 WebRequest 和 WebResponse 从 publicsuffix.org 自动下载最新列表。

所以它会变得更有用并且总是更新。(2) 和 (3) 不会有问题,但 (1) 是我现在的重点。

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

转换器工具可能有用,但更好的是我逐行查看和修改它。

现在我的问题是如何转换它?例如来自 DomainNames 类中 FindMatchingTLDRule 方法的代码:

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

我相信不涉及数据库,只是以他们处理集合的方式。

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

谢谢

呼叫MeLaNN

4

2 回答 2

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 to Objects for .NET 2.0 的重新实现......现在它是开源的:)

于 2009-10-09T07:03:21.837 回答
1

感谢 Jon Skeet,这对我很有帮助。它工作得很好,所有的单元测试都成功通过了。

在这里,我想与任何想在 .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<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.ToList() 来获取列表。由于“var exceptionresults”更改为“List exceptionresults”.ToList() 应该被删除。

呼叫MeLaNN

于 2009-10-09T09:45:40.510 回答