对多个对象执行类似的操作而仅需一个调用差异?

时间:2018-08-13 21:56:10

标签: c# entity-framework

我正在尝试重构以前的开发人员编写的一些代码,而我正在绞尽脑汁,试图提出一种处理此特定用例的好方法。我们有一个名为ProcessMessage的方法,该方法具有一个switch语句来处理一些基本的字符串替换,但是每个switch实例都有一个要提取的特定对象类型和一个要调用的特定方法。其余操作非常相似。

首先,我简化了开关,但是我认为可能有一种方法可以进一步简化它。我当时想使用泛型是可能的,但是不幸的是,这些对象是由数据库优先实体框架上下文生成的实体,因此我不能做太多事情来修改其基础类型或它们可能继承的任何接口。

这是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。是否有一个很好的方法可以将这三种方法组合成一个调用而不接触基础实体?

1 个答案:

答案 0 :(得分:1)

考虑一下,每个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情况的方式生成该Dictionary,例如:

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;