C# 重构类似的方法

C# 重构类似的方法,c#,refactoring,C#,Refactoring,使用这种代码: public void UpdateCellFont(int id, string colName, Font font) { CellLocation location = new CellLocation(id, colName); if (CellAppearances.ContainsKey(location)) { CellAppearances[location].Font =

使用这种代码:

    public void UpdateCellFont(int id, string colName, Font font)
    {
        CellLocation location = new CellLocation(id, colName);

        if (CellAppearances.ContainsKey(location))
        {
            CellAppearances[location].Font = font;
        }
        else
        {
            CellAppearance cell = new CellAppearance(font, _DefaultBackColor, _DefaultForeColor);
            CellAppearances.Add(location, cell);
        }
    }

    public void UpdateCellBackColor(int id, string colName, Color backColor)
    {
        CellLocation location = new CellLocation(id, colName);

        if (CellAppearances.ContainsKey(location))
        {
            CellAppearances[location].BackColor = backColor;
        }
        else
        {
            CellAppearance cell = new CellAppearance(_DefaultFont, backColor, _DefaultForeColor);
            CellAppearances.Add(location, cell);
        }
    }

    public void UpdateCellForeColor(int id, string colName, Color foreColor)
    {
        CellLocation location = new CellLocation(id, colName);

        if (CellAppearances.ContainsKey(location))
        {
            CellAppearances[location].ForeColor = foreColor;
        }
        else
        {
            CellAppearance cell = new CellAppearance(_DefaultFont, _DefaultBackColor, foreColor);
            CellAppearances.Add(location, cell);
        }
    }
这些方法都做了几乎相同的事情——每个方法都会更新字体、背景色或前景色(或者如果字典中没有条目,它们会创建一个新条目)

当它们作用于强类型的cell外观时,如何减少重复


谢谢

您可能需要使用反射来将代码概括为几个不同类型的字段。不确定这是否值得。

那么直接说怎么样

public CellAppearance GetAppearance(int id, string colName){
    var location = new CellLocation(id, colName);
    if(!CellAppearances.ContainsKey(location))
       CellAppearances.Add(location, cell);
    return CellAppearances[location];
}

// usage:
GetAppearance(1,"hello").Font = myFont;
GetAppearance(2,"blubb").BackColor = myColor;
救援代表们! 在这种情况下,He的答案应该符合要求,但通常情况下,您可以通过使用委托作为方法参数(并以稍微不同的方式组织您的主要方法)来解决此类情况:

public void UpdateCellProperty(int-id,string-colName,
动作外观(动作)
{
细胞外观细胞;
CellLocation location=新的CellLocation(id,colName);
if(CellAppearancess.ContainsKey(位置))
{
单元=单元外观[位置];
}
其他的
{
单元格=新的单元格外观(\u DefaultFont,\u DefaultBackColor,
_前景色);
}
外观作用(细胞);
}
public void UpdateCellFont(int-id、字符串colName、字体)
{
UpdateCellProperty(id,colName,c=>c.Font=Font);
}
public void UpdateCellBackColor(int id、字符串colName、颜色backColor)
{
UpdateCellProperty(id,colName,c=>c.BackColor=BackColor);
}
public void UpdateCellForeColor(int-id、字符串colName、颜色foreColor)
{
UpdateCellProperty(id,colName,c=>c.ForeColor=ForeColor);
}

我看到这种模式被称为“中间模式中的空洞”。非常恰当:你定义了一个带有“洞”的方法体。这是与委托一起注入的。

正是这些方法的条件性使它们变得复杂和重复。如果外观已经存在,则执行一件事;如果外观不存在,则执行另一件事。因此,请确保外观存在:

public void EnsureCellAppearance(CellLocation location)
{
    if (CellAppearances.ContainsKey(location))
        return;
    CellAppearances.Add(location, new CellAppearance(_DefaultFont, _DefaultBackColor, _DefaultForeColor));
}
现在你的方法简单多了:

public void UpdateCellFont(int id, string colName, Font font)
{
    CellLocation location = new CellLocation(id, colName);
    EnsureCellAppearance(location);
    CellAppearances[location].Font = font;
}

@你的意思是-1?:)都一样。你是对的,它不像你的解决方案那么简洁,但我想指出一个“重构类似方法”的通用模式。它在很多场合对我都有好处。它将重复部分从可变代码中分离出来。核心方法往往非常稳定,在学员中,您可以在没有仪式代码的情况下专注于任务本身。是的,这是其中的一部分-但请注意,需要更新的是字体、背景色和前景色(实际上还有更多,但为了清晰起见,我将其缩减)。所以我仍然需要三个方法——UpdateCellFont、UpdateForeColor、UpdateBackColor……好的,所以“cell”将使用默认值创建。然后我仍然有三个方法(UpdateFont、UpdateBackColor、UpdateFolector),但它们应该只调用一行GetAppearance(id,“colName”)。Font=Font等?是的。。。正确的。。在您的解决方案中,您甚至可以先创建默认样式,然后更新特定设置。。。我觉得这样简单明了…我不知道如何接受你的改变。。。看起来不错——比我的更正确;)
public void UpdateCellFont(int id, string colName, Font font)
{
    CellLocation location = new CellLocation(id, colName);
    EnsureCellAppearance(location);
    CellAppearances[location].Font = font;
}