首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在枚举上切换大小写,从IMapper返回特定的映射对象

在枚举上切换大小写,从IMapper返回特定的映射对象
EN

Code Review用户
提问于 2022-12-07 17:06:37
回答 3查看 855关注 0票数 4

我有一个不断增长的开关案例陈述,我计划增加3多个案例陈述。给定一个int,将其与枚举进行比较,并调用IMapper.Map<TDestination>(sourceObject);

代码语言:javascript
复制
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()。不过,代码要小得多!下面是我提出的基于字典的解决方案,以及方法代码是什么样子的。

代码语言:javascript
复制
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,那么它可能会很高兴。

EN

回答 3

Code Review用户

回答已采纳

发布于 2022-12-07 17:48:15

您可以使用一个开关表达式(C# 8)而不是一个switch语句来使代码变得更小:

代码语言:javascript
复制
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。你想要搜索第一次出现吗?

代码语言:javascript
复制
int mappingId = mappings
   .FirstOrDefault(m => request.WorkflowCode == m.WorkflowCode)?.EventHandlerId ?? 0;

至于使用字典的解决方案,您可以声明

代码语言:javascript
复制
Dictionary<WorkflowEventHandler,
            Func<IMapper, WebhookActivityRequest, WebhookActivity>>

而不是。也就是说,您可以将它添加到lambda表达式中来完成这项工作。

代码语言:javascript
复制
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) }
};

然后你就可以像这样使用它

代码语言:javascript
复制
if (workflowEventHandlers.TryGetValue((WorkflowEventHandler)mappingId, out var mapCreator)) {
    command = mapCreator(_mapper, request);
} else {
    command = _mapper.Map<ConsecutiveCaseCreated>(request);
}
票数 5
EN

Code Review用户

发布于 2022-12-07 20:57:11

与其在单独的数据结构中列出映射,不如使用自定义属性来用mapTo信息装饰/注释每个枚举值。

代码语言:javascript
复制
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的定义可以这么简单

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Field)]
class WorkflowEventHandlerMapAttribute: Attribute
{
    public Type MapTo { get; init; }
    public WorkflowEventHandlerMapAttribute(Type MapTo) => MapTo = mapTo;
}

通过反射,可以检索相关的属性实例,如下所示:

代码语言:javascript
复制
var handler = WorkflowEventHandler.CONSECUTIVE_CASE_CREATED;
var attribute = typeof(WorkflowEventHandler)
    .GetField(handler.ToString())
    .GetCustomAttributes(typeof(WorkflowEventHandlerMapAttribute), false)
    .FirstOrDefault() as WorkflowEventHandlerMapAttribute;

最后,您可以使用attribute.MapTo获得上述handlerConsecutiveCaseCreated类型。

在这里,您可以找到一个关于dotnet小提琴的工作示例.

票数 4
EN

Code Review用户

发布于 2022-12-07 23:42:04

由于您使用的是AutoMapper,我相信您已经完成了映射配置文件。为此,您可以通过使用自定义目标转换、使用ConvertUsingConstructUsing来扩展工作。这也是可能的,因为所有类都是从WebhookActivity派生的。

您可以创建一个同时保存commandWorkflowEventHandler值的模型,然后使用AutoMapper映射该模型并在ConvertUsing中使用switch

AutoMapper配置示例:

代码语言:javascript
复制
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)
                };
            });

    }
}

现在,您的方法应该是这样的:

代码语言:javascript
复制
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;
}
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/281757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档