首页 > 解决方案 > 对多个对象执行类似的操作,只有一个调用差异?

问题描述

我正在尝试重构一些由以前的开发人员编写的代码,并且我正在绞尽脑汁试图想出一个处理这个特定用例的好方法。我们有一个调用的方法ProcessMessage,它有一个 switch 语句来处理一些基本的字符串替换,但是每个 switch case 都有它正在获取的特定对象类型,以及它正在调用的特定方法。其余的操作非常相似。

首先,我简化了开关,但我认为可能有一种方法可以进一步简化它。我在想使用泛型可能是可能的,但不幸的是,这些对象是由数据库优先实体框架上下文生成的实体,所以我无法修改它们的底层类型或它们可能继承的任何接口。

这是 switch 语句和几个辅助方法的示例:

private string ProcessMessage(int? userId, int? resourceId, int? reminderId, string processedMessage)
{
    var sourceEntityList = _replacementKeywords.Select(x => x.SourceEntity).Distinct().ToList();
    foreach (var sourceEntity in sourceEntityList)
    {
        var sourcekeyWords = _replacementKeywords.Where(x => x.SourceEntity == sourceEntity).Select(x => x.ReplacementText).ToList();
        switch (sourceEntity)
        {
            case "User":
                if (userId.HasValue)
                {
                    var user = _userRepository.GetById(userId);

                    processedMessage = GetReplacementValue(user, sourcekeyWords, processedMessage);
                }

                break;
            case "Reminder":
                if (reminderId.HasValue)
                {
                    var ar = _reminderRepository.GetById(reminderId.Value);

                    processedMessage = GetReplacementValue(ar, sourcekeyWords, processedMessage);
                }

                break;
            case "Resource":
                if (resourceId.HasValue)
                {
                    var scheduleResource = _schedulingRepository.GetresourceIdById(resourceId.Value);

                    processedMessage = GetReplacementValue(scheduleResource, sourcekeyWords, processedMessage);
                }
                break;
        }
    }

    return processedMessage;
}

private static string GetReplacementValue(User user, IEnumerable<string> sourceKeywords, string message)
{
    var processedMessage = message;
    foreach (var userKeyword in sourceKeywords)
    {
        if (!processedMessage.Contains(userKeyword)) continue;

        var replaceValue = GetPatientInfoFromUser(user, userKeyword);
        processedMessage = processedMessage.Replace(userKeyword, replaceValue);
    }

    return processedMessage;
}

private static string GetReplacementValue(Reminder reminder,
    IEnumerable<string> sourceKeywords, string message)
{
    var processedMessage = message;
    foreach (var apptReminder in sourceKeywords)
    {
        if (!processedMessage.Contains(apptReminder)) continue;

        var replaceValue = GetReminderInfo(reminder, apptReminder);
        processedMessage = processedMessage.Replace(apptReminder, replaceValue);
    }

    return processedMessage;
}

private static string GetReplacementValue(Resource resource,
    IEnumerable<string> sourceKeywords, string message)
{
    var processedMessage = message;
    foreach (var resourceKeyword in sourceKeywords)
    {
        if (!processedMessage.Contains(scheduleResourceKeyword)) continue;

        var replaceValue = GetResourceInfo(resource, resourceKeyword);
        processedMessage = processedMessage.Replace(resourceKeyword, replaceValue);
    }

    return processedMessage;
}

您将注意到的主要事情是,三个辅助方法中的每一个都有效地执行完全相同的功能,除了它们调用哪个方法来获取replaceValue. 有没有一种在不触及底层实体的情况下将这三种方法组合成一个调用的好方法?

标签: c#entity-framework

解决方案


如果你仔细想想,每个GetReplacementValue人都有两个责任:

  1. 枚举sourceKeywords到进程message
  2. 调用一些函数来获取替换message数据的值

让我们从那里取出第二个责任,让它一次性全部重用:

private static string GetReplacementValue(Dictionary<string, string> replacementValues, string message)
{
    string processedMessage = message;

    foreach (var item in replacementValues)
    {
        processedMessage = processedMessage.Replace(item.Key, item.Value);
    }

    return processedMessage;
}

现在您只需要以对当前情况有意义的方式生成该字典switch,例如:

case "User":
    if (userId.HasValue)
    {
        var user = _userRepository.GetById(userId);
        var replacementValues = sourcekeyWords
            .Where(x => processedMessage.Contains(x))
            // .Key will be the keyword and .Value will have the replacement value
            .ToDictionary(x => x, x => GetPatientInfoFromUser(user, x));

        processedMessage = GetReplacementValue(replacementValues, processedMessage);
    }

    break;

推荐阅读