重构帮助c#

Hca*_*tek 2 c# refactoring design-patterns

我有几百行代码,如下所示:

if (c.SomeValue == null || c.SomeProperty.Status != 'Y')
{
    btnRecordCall.Enabled = false;
}

if (c.SomeValue == null || (c.SomeProperty.Status != 'Y' &&
    c.SomeOtherPropertyAction != 'Y'))
{
    btnAddAction.Enabled = false;
}

if (c.SomeValue == null || c.SomeProperty.Processing != 'Y')
{
    btnProcesss.Enabled = false;
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能正确地重构这个?我看到每次调用检查'c.SomeValue == null',但它包含在其他条件中.我怎么可能消除这个重复的代码?

48k*_*ocs 5

如果您不想进行太多重构,您可以轻松地取消空检查。

if (c.SomeValue == null)
{
    btnRecordCall.Enabled = false;
    btnAddAction.Enabled = false;
    btnProcesss.Enabled = false;
}
else
{
    if(c.SomeProperty.Status != 'Y')
    {
        btnRecordCall.Enabled = false;
    }

    if((c.SomeProperty.Status != 'Y') &&
       (c.SomeOtherPropertyAction != 'Y'))
    {
        btnAddAction.Enabled = false;
    }

    if(c.SomeProperty.Processing != 'Y')
    {
        btnProcesss.Enabled = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您希望重构而不是洗牌,则布尔测试墙可以移至对象 c 是其实例的任何类的方法/扩展方法中 - 这样您可以说

btnRecordCall.Enabled = c.IsRecordCallAllowed();
Run Code Online (Sandbox Code Playgroud)


eul*_*rfx 5

我将使用规范模式,并构建映射到适当的Enabled值的复合规范.

您要回答的整体问题是某个对象c是否满足给定条件,然后允许您决定是否要启用某些内容.那么你有这个界面:

interface ICriteria<T>
{
    bool IsSatisfiedBy(T c);
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码将如下所示:

ICriteria<SomeClass> cr = GetCriteria();

btnAddAction.Enabled = cr.IsSatisfiedBy(c);
Run Code Online (Sandbox Code Playgroud)

下一步是撰写合适的ICriteria对象.您可以使用另一个ICriteria实现(另外还有Or和And),名为PredicateCriteria,如下所示:

class PredicateCriteria<T>  : ICriteria<T>
{
    public PredicateCriteria(Func<T, bool> p) {
        this.predicate = p;
    }

    readonly Func<T, bool> predicate;

    public bool IsSatisfiedBy(T item) {
        return this.predicate(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

其中一个例子是:

var c = new PredicateCriteria<SomeClass>(c => c.SomeValue != null);
Run Code Online (Sandbox Code Playgroud)

其余的将是与其他标准的组成.