【问题标题】:Refactoring two methods down to one将两种方法重构为一种
【发布时间】:2012-10-15 15:15:58
【问题描述】:

我有两种方法几乎可以做同样的事情。他们根据 state OR state 和 schoolType 得到一个List<XmlNode>,然后返回一个不同的、有序的IEnumerable<KeyValuePair<string,string>>。我知道它们可以重构,但我正在努力确定方法返回中 linq 语句的参数应该是什么类型(每个方法的最后一行)。

提前感谢您的帮助。

private IEnumerable<KeyValuePair<string, string>> getAreaDropDownDataSource() {
    StateInfoXmlDocument stateInfoXmlDocument = new StateInfoXmlDocument();
    string schoolTypeXmlPath = string.Format(STATE_AND_SCHOOL_TYPE_XML_PATH, StateOfInterest, ConnectionsLearningSchoolType);
    var schoolNodes = new List<XmlNode>(stateInfoXmlDocument.SelectNodes(schoolTypeXmlPath).Cast<XmlNode>());
    return schoolNodes.Select(x => new KeyValuePair<string, string>(x.Attributes["idLocation"].Value, x.Value)).OrderBy(x => x.Key).Distinct();
}

private IEnumerable<KeyValuePair<string, string>> getStateOfInterestDropDownDataSource() {
    StateInfoXmlDocument stateInfoXmlDocument = new StateInfoXmlDocument();
    string schoolTypeXmlPath = string.Format(SCHOOL_TYPE_XML_PATH, ConnectionsLearningSchoolType);
    var schoolNodes = new List<XmlNode>(stateInfoXmlDocument.SelectNodes(schoolTypeXmlPath).Cast<XmlNode>());
    return schoolNodes.Select(x => new KeyValuePair<string, string>(x.Attributes["stateCode"].Value, x.Attributes["stateName"].Value)).OrderBy(x => x.Key).Distinct();
}

【问题讨论】:

    标签: c# linq refactoring


    【解决方案1】:

    提取节点检索到单独的方法/属性。我还建议使用不同的属性/方法来提取学校和状态节点:

    private List<XmlNode> GetNodes(string xPath)
    {
        XmlDocument stateInfoXmlDocument = new XmlDocument();
        return new List<XmlNode>(stateInfoXmlDocument.SelectNodes(xPath)
                                                     .Cast<XmlNode>());
    }
    
    private List<XmlNode> SchoolNodes
    {
        get { return GetNodes(String.Format(SCHOOL_PATH, LearningSchoolType)); }
    }
    
    private List<XmlNode> StateNodes
    {
        get { return GetNodes(String.Format(STATE_PATH, StateOfInterest)); }
    }   
    

    使用学校和州节点的联合来检索区域节点:

    private IEnumerable<KeyValuePair<string, string>> GetAreaDropDownDataSource()
    {
        return SchoolNodes.Union(StateNodes)
                .Select(x => new KeyValuePair<string, string>(x.Attributes["idLocation"].Value, x.Value))
                .OrderBy(x => x.Key)
                .Distinct();
    }
    
    private IEnumerable<KeyValuePair<string, string>> GetStateOfInterestDropDownDataSource()
    {
        return SchoolNodes
            .Select(x => new KeyValuePair<string, string>(x.Attributes["stateCode"].Value, x.Attributes["stateName"].Value))
            .OrderBy(x => x.Key)
            .Distinct();
    }
    

    您还可以使用Func&lt;XmlNode, KeyValuePair&lt;string, string&gt;&gt; 类型的不同选择器并将它们传递给将创建数据源的方法:

    private IEnumerable<KeyValuePair<string, string>> GetDropDownDataSource(
            List<XmlNode> nodes,
            Func<XmlNode, KeyValuePair<string, string>> selector)
    {
        return nodes.Select(selector)
                    .OrderBy(x => x.Key)
                    .Distinct();
    }
    

    【讨论】:

    • @lc。谢谢,没注意到。从属性更改为方法
    • 谢谢,这里有一些非常棒的想法 :)
    【解决方案2】:

    我觉得虽然它们都返回IEnumerable&lt;KeyValuePair&lt;string,string&gt;&gt;,但这些方法在内容上的语义完全不同。因此,我会保留这两种方法,只将重复的代码提取到第三个。比如:

    private List<XmlNode> getSchoolNodes(string xmlPath, params object[] values)
    {
        StateInfoXmlDocument stateInfoXmlDocument = new StateInfoXmlDocument();
        string schoolTypeXmlPath = string.Format(xmlPath, values);
        return new List<XmlNode>(stateInfoXmlDocument.SelectNodes(schoolTypeXmlPath).Cast<XmlNode>());
    }
    
    private IEnumerable<KeyValuePair<string, string>> getAreaDropDownDataSource() {
        var schoolNodes = getSchoolNodes(STATE_AND_SCHOOL_TYPE_XML_PATH, StateOfInterest, ConnectionsLearningSchoolType);        
        return schoolNodes.Select(x => new KeyValuePair<string, string>(x.Attributes["idLocation"].Value, x.Value)).OrderBy(x => x.Key).Distinct();
    }
    
    private IEnumerable<KeyValuePair<string, string>> getStateOfInterestDropDownDataSource() {
        var schoolNodes = getSchoolNodes(SCHOOL_TYPE_XML_PATH, ConnectionsLearningSchoolType);
        return schoolNodes.Select(x => new KeyValuePair<string, string>(x.Attributes["stateCode"].Value, x.Attributes["stateName"].Value)).OrderBy(x => x.Key).Distinct();
    }
    

    您可以做到以下几点,但我想知道这是否是过度设计问题并造成调用两个Funcs 的开销。

    private IEnumerable<KeyValuePair<string, string>> getSchoolNodeDataSource(Func<XmlNode, string> keyFunc, Func<XmlNode, string> valueFunc, string xmlPath, params object[] values)
    {
        StateInfoXmlDocument stateInfoXmlDocument = new StateInfoXmlDocument();
        string schoolTypeXmlPath = string.Format(xmlPath, values);
        var schoolNodes = new List<XmlNode>(stateInfoXmlDocument.SelectNodes(schoolTypeXmlPath).Cast<XmlNode>());
        return schoolNodes.Select(x => new KeyValuePair<string, string>(keyFunc(x), valueFunc(x))).OrderBy(x => x.Key).Distinct();
    }
    
    private IEnumerable<KeyValuePair<string, string>> getAreaDropDownDataSource() {
        return getSchoolNodeDataSource(x => x.Attributes["idLocation"].Value, x => x.Value,
            STATE_AND_SCHOOL_TYPE_XML_PATH, StateOfInterest, ConnectionsLearningSchoolType);        
    }
    
    private IEnumerable<KeyValuePair<string, string>> getStateOfInterestDropDownDataSource() {
        return getSchoolNodeDataSource(x => x.Attributes["stateCode"].Value, x => x.Attributes["stateName"].Value, 
            SCHOOL_TYPE_XML_PATH, ConnectionsLearningSchoolType);
    }
    

    【讨论】:

      【解决方案3】:
      private IEnumerable<KeyValuePair<string, string>> Foo(
          string schoolTypeXmlPath,
          Func<T, string> keySelector,
          Func<T, string> valueSelector)
      {
          return (
              from XmlNode x in StateInfoXmlDocument().SelectNodes(schoolTypeXmlPath)
              orderby x.Key
              select new KeyValuePair<string, string>(keySelector(x), valueSelector(x)))
              .Distinct()
      }
      
      private IEnumerable<KeyValuePair<string, string>> getAreaDropDownDataSource() {
          return Foo(
              string.Format(STATE_AND_SCHOOL_TYPE_XML_PATH, StateOfInterest, ConnectionsLearningSchoolType),
              x => x.Attributes["idLocation"].Value,
              x => x.Value);
      }
      
      private IEnumerable<KeyValuePair<string, string>> getStateOfInterestDropDownDataSource() {
          return Foo(
              string.Format(SCHOOL_TYPE_XML_PATH, ConnectionsLearningSchoolType),
              x => x.Attributes["stateCode"].Value,
              x => x.Attributes["stateName"].Value);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-25
        • 2010-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-08
        • 1970-01-01
        相关资源
        最近更新 更多