我有一个不断增长的开关案例陈述,我计划增加3多个案例陈述。给定一个int,将其与枚举进行比较,并调用IMapper.Map<TDestination>(sourceObject);
public WebhookActivity MakeMessage(WebhookActivityRequest request)
{
WebhookActivity command = _mapper.Map<ConsecutiveCaseCreated>(request);
var mappingId = 0;
for(int i = 0; i < mappings.Length; i++)
{
if(request.WorkflowCode == mappings[i].WorkflowCode)
{
mappingId = mappings[i].EventHandlerId;
}
}
switch(mappingId)
{
case (int)WorkflowEventHandler.CONSECUTIVE_CASE_CREATED:
{
command = _mapper.Map<ConsecutiveCaseCreated>(request);
break;
}
case (int)WorkflowEventHandler.CONSECUTIVE_CASE_MODIFIED:
{
command = _mapper.Map<ConsecutiveCaseModified>(request);
break;
}
case (int)WorkflowEventHandler.CONSECUTIVE_CASE_CANCELLED:
{
command = _mapper.Map<ConsecutiveCaseCancelled>(request);
break;
}
case (int)WorkflowEventHandler.INTERMITTENT_CASE_CREATED:
{
command = _mapper.Map<IntermittentCaseCreated>(request);
break;
}
case (int)WorkflowEventHandler.INTERMITTENT_CASE_TIME_ADJUSTED:
{
command = _mapper.Map<IntermittentCaseTimeAdjusted>(request);
break;
}
case (int)WorkflowEventHandler.INTERMITTENT_CASE_TIME_DELETED:
{
command = _mapper.Map<IntermittentCaseTimeDeleted>(request);
break;
}
case (int)WorkflowEventHandler.CASE_CHANGED_TYPE:
{
command = _mapper.Map<CaseChangedType>(request);
break;
}
}
return command;
}我查看了其他与枚举相关的问题,并看到了使用字典的常见解决方案。我试过了,但不太清楚如何调用IMapper.Map()。不过,代码要小得多!下面是我提出的基于字典的解决方案,以及方法代码是什么样子的。
private static readonly Dictionary<int, Type> workflowEventHandlers = new Dictionary<int, Type>
{
{ (int)WorkflowEventHandler.CONSECUTIVE_CASE_CREATED, typeof(ConsecutiveCaseCreated)},
{ (int)WorkflowEventHandler.CONSECUTIVE_CASE_CANCELLED, typeof(ConsecutiveCaseCancelled) },
{ (int)WorkflowEventHandler.CONSECUTIVE_CASE_MODIFIED, typeof(ConsecutiveCaseModified) },
{ (int)WorkflowEventHandler.INTERMITTENT_CASE_CREATED, typeof(IntermittentCaseCreated) },
{ (int)WorkflowEventHandler.INTERMITTENT_CASE_TIME_ADJUSTED, typeof(IntermittentCaseTimeAdjusted) },
{ (int)WorkflowEventHandler.INTERMITTENT_CASE_TIME_DELETED, typeof(IntermittentCaseTimeDeleted) },
{ (int)WorkflowEventHandler.CASE_CHANGED_TYPE, typeof(CaseChangedType) }
};
public WebhookActivity MakeMessage(WebhookActivityRequest request)
{
WebhookActivity command = _mapper.Map<ConsecutiveCaseCreated>(request);
var mappingId = 0;
for(int i = 0; i < mappings.Length; i++)
{
if(request.WorkflowCode == mappings[i].WorkflowCode)
{
mappingId = mappings[i].EventHandlerId;
}
}
if(workflowEventHandlers.TryGetValue(mappingId, out Type mapDestinationType))
{
//command = _mapper.Map(request, typeof(WebhookActivityRequest), mapDestinationType);
//command = Map(request, mapDestinationType);
}
}
// doesn't really work
private WebhookActivityMessage Map<TSource, TDestination>(TSource source, TDestination destination) where TDestination: WebhookActivityMessage
{
return _mapper.Map<TSource, TDestination>(source);
}目标类型都是从一个名为WebhookActivityMessage的基类继承的,这个基类继承自WebhookActivity,所以我想如果我可以说我的Map()方法的返回类型是WebhookActivityMessage,那么它可能会很高兴。
发布于 2022-12-07 17:48:15
您可以使用一个开关表达式(C# 8)而不是一个switch语句来使代码变得更小:
public WebhookActivity MakeMessage(WebhookActivityRequest request)
{
int mappingId = 0;
for (int i = 0; i < mappings.Length; i++) {
if (request.WorkflowCode == mappings[i].WorkflowCode) {
mappingId = mappings[i].EventHandlerId;
}
}
return (WorkflowEventHandler)mappingId switch {
WorkflowEventHandler.CONSECUTIVE_CASE_CREATED => _mapper.Map<ConsecutiveCaseCreated>(request),
WorkflowEventHandler.CONSECUTIVE_CASE_MODIFIED => _mapper.Map<ConsecutiveCaseModified>(request),
WorkflowEventHandler.CONSECUTIVE_CASE_CANCELLED => _mapper.Map<ConsecutiveCaseCancelled>(request),
WorkflowEventHandler.INTERMITTENT_CASE_CREATED => _mapper.Map<IntermittentCaseCreated>(request),
WorkflowEventHandler.INTERMITTENT_CASE_TIME_ADJUSTED => _mapper.Map<IntermittentCaseTimeAdjusted>(request),
WorkflowEventHandler.INTERMITTENT_CASE_TIME_DELETED => _mapper.Map<IntermittentCaseTimeDeleted>(request),
WorkflowEventHandler.CASE_CHANGED_TYPE => _mapper.Map<CaseChangedType>(request),
_ => _mapper.Map<ConsecutiveCaseCreated>(request)
};
}但是请注意,只使用for-循环中的最后一个mappingId。你想要搜索第一次出现吗?
int mappingId = mappings
.FirstOrDefault(m => request.WorkflowCode == m.WorkflowCode)?.EventHandlerId ?? 0;至于使用字典的解决方案,您可以声明
Dictionary<WorkflowEventHandler,
Func<IMapper, WebhookActivityRequest, WebhookActivity>>而不是。也就是说,您可以将它添加到lambda表达式中来完成这项工作。
private static readonly Dictionary<WorkflowEventHandler, Func<IMapper, WebhookActivityRequest, WebhookActivity>> workflowEventHandlers = new(){
{ WorkflowEventHandler.CONSECUTIVE_CASE_CREATED, (m, r) => m.Map<ConsecutiveCaseCreated>(r) },
{ WorkflowEventHandler.CONSECUTIVE_CASE_CANCELLED, (m, r) => m.Map<ConsecutiveCaseCancelled>(r) },
{ WorkflowEventHandler.CONSECUTIVE_CASE_MODIFIED, (m, r) => m.Map<ConsecutiveCaseModified>(r) },
{ WorkflowEventHandler.INTERMITTENT_CASE_CREATED, (m, r) => m.Map<IntermittentCaseCreated>(r) },
{ WorkflowEventHandler.INTERMITTENT_CASE_TIME_ADJUSTED,(m, r) => m.Map<IntermittentCaseTimeAdjusted>(r) },
{ WorkflowEventHandler.INTERMITTENT_CASE_TIME_DELETED, (m, r) => m.Map<IntermittentCaseTimeDeleted>(r) },
{ WorkflowEventHandler.CASE_CHANGED_TYPE, (m, r) => m.Map<CaseChangedType>(r) }
};然后你就可以像这样使用它
if (workflowEventHandlers.TryGetValue((WorkflowEventHandler)mappingId, out var mapCreator)) {
command = mapCreator(_mapper, request);
} else {
command = _mapper.Map<ConsecutiveCaseCreated>(request);
}发布于 2022-12-07 20:57:11
与其在单独的数据结构中列出映射,不如使用自定义属性来用mapTo信息装饰/注释每个枚举值。
enum WorkflowEventHandler
{
[WorkflowEventHandlerMap(typeof(ConsecutiveCaseCreated))]
CONSECUTIVE_CASE_CREATED = 1,
[WorkflowEventHandlerMap(typeof(ConsecutiveCaseCancelled))]
CONSECUTIVE_CASE_CANCELLED = 2,
[WorkflowEventHandlerMap(typeof(ConsecutiveCaseModified))]
CONSECUTIVE_CASE_MODIFIED = 3,
[WorkflowEventHandlerMap(typeof(IntermittentCaseCreated))]
INTERMITTENT_CASE_CREATED = 4,
[WorkflowEventHandlerMap(typeof(IntermittentCaseTimeAdjusted))]
INTERMITTENT_CASE_TIME_ADJUSTED = 5,
[WorkflowEventHandlerMap(typeof(IntermittentCaseTimeDeleted))]
INTERMITTENT_CASE_TIME_DELETED = 6,
[WorkflowEventHandlerMap(typeof(CaseChangedType))]
CASE_CHANGED_TYPE = 7
}WorkflowEventHandlerMapAttribute的定义可以这么简单
[AttributeUsage(AttributeTargets.Field)]
class WorkflowEventHandlerMapAttribute: Attribute
{
public Type MapTo { get; init; }
public WorkflowEventHandlerMapAttribute(Type MapTo) => MapTo = mapTo;
}通过反射,可以检索相关的属性实例,如下所示:
var handler = WorkflowEventHandler.CONSECUTIVE_CASE_CREATED;
var attribute = typeof(WorkflowEventHandler)
.GetField(handler.ToString())
.GetCustomAttributes(typeof(WorkflowEventHandlerMapAttribute), false)
.FirstOrDefault() as WorkflowEventHandlerMapAttribute;最后,您可以使用attribute.MapTo获得上述handler的ConsecutiveCaseCreated类型。
发布于 2022-12-07 23:42:04
由于您使用的是AutoMapper,我相信您已经完成了映射配置文件。为此,您可以通过使用自定义目标转换、使用ConvertUsing或ConstructUsing来扩展工作。这也是可能的,因为所有类都是从WebhookActivity派生的。
您可以创建一个同时保存command和WorkflowEventHandler值的模型,然后使用AutoMapper映射该模型并在ConvertUsing中使用switch。
public class WebhookActivityRequestModel
{
public WebhookActivity? Source { get; set; }
public WorkflowEventHandler Name { get; set; }
public WebhookActivityRequestModel() { }
public WebhookActivityRequestModel(WebhookActivity? source, WorkflowEventHandler name)
{
Source = source;
Name = name;
}
}
public class WorkflowEventHandlerProfile : Profile
{
public WorkflowEventHandlerProfile()
{
CreateMap<WebhookActivity, ConsecutiveCaseCreated>();
CreateMap<WebhookActivity, ConsecutiveCaseModified>();
CreateMap<WebhookActivityRequestModel, WebhookActivity>()
.ConvertUsing((source, dest, context) =>
{
return source.Name switch
{
WorkflowEventHandler.CONSECUTIVE_CASE_CREATED => context.Mapper.Map<ConsecutiveCaseCreated>(source.Source),
WorkflowEventHandler.CONSECUTIVE_CASE_MODIFIED => context.Mapper.Map<ConsecutiveCaseModified>(source.Source),
_ => context.Mapper.Map<ConsecutiveCaseCreated>(source.Source)
};
});
}
}现在,您的方法应该是这样的:
public WebhookActivity MakeMessage(WebhookActivityRequest request)
{
WebhookActivity command = _mapper.Map<ConsecutiveCaseCreated>(request);
int mappingId = mappings
.FirstOrDefault(m => request.WorkflowCode == m.WorkflowCode)?.EventHandlerId ?? 0;
if(Enum.TryParse(typeof(WorkflowEventHandler), mappingId.ToString(), out var result))
{
var model = new WebhookActivityRequestModel(command, result);
return _mapper.Map<WebhookActivityRequestModel, WebhookActivity>(model);
}
return command;
}https://codereview.stackexchange.com/questions/281757
复制相似问题