将两种方法重构为一种

时间:2012-10-15 15:15:58

标签: c# linq refactoring

我有两种方法几乎可以做同样的事情。他们根据州OR状态和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();
}

3 个答案:

答案 0 :(得分:4)

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

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<XmlNode, KeyValuePair<string, string>>类型的不同选择器,并将它们传递给将创建数据源的方法:

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

答案 1 :(得分:2)

我觉得当他们都返回IEnumerable<KeyValuePair<string,string>>时,这些方法在内容上在语义上完全不同。因此,我会保留这两种方法,只将重复的代码提取到第三种。类似的东西:

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();
}

你可以进行以下操作,但我想知道这是否过度设计了这个问题并创建了调用两个Func的开销。

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);
}

答案 2 :(得分:0)

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);
}