c# - 对多个对象执行类似的操作,只有一个调用差异?
问题描述
我正在尝试重构一些由以前的开发人员编写的代码,并且我正在绞尽脑汁试图想出一个处理这个特定用例的好方法。我们有一个调用的方法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
. 有没有一种在不触及底层实体的情况下将这三种方法组合成一个调用的好方法?
解决方案
如果你仔细想想,每个GetReplacementValue
人都有两个责任:
- 枚举
sourceKeywords
到进程message
- 调用一些函数来获取替换
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;
推荐阅读
- php - 我的一些输入字段没有发布到 php
- ruby-on-rails - 没有找到 LeadsController#create 的模板,渲染头:no_content
- html - 使用 HTML + 辅助功能,是否有显示“此内容的音频可用”的标准?
- css - 边缘问题:CSS 网格单元格中的高度 100% 获得 100% 宽度的值
- jmeter - 在 JMeter 中,如何从 REST POST 请求(而不是响应)中捕获值?
- node.js - 在 NodeJS 中访问 AWS SSM 参数
- javascript - 使用背景图像显示存储为数据 URI 的 SVG:为什么属性值无效?
- php - PHP 套接字在几分钟后过期
- .net - 对于 IBM.WMQ .Net 参考,为什么我的代码没有加载应用程序特定版本的 amqmdnet.dll?
- sql-server - 在 SQL Server 中获取“_”之后和之前的数据