CQRS-避免将大小写切换为调用命令处理程序

问题描述 投票:1回答:1

我正在使用CQRS设计模式。我有15种以上与每种事件类型相对应的命令处理程序。我想避免在切换情况下根据事件类型调用相应的命令处理程序。

这是我的Azure功能:

[FunctionName("ReceiveEvent")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            //log.LogInformation("ReceiveEvent HTTP trigger function started processing request.");

            //log.LogInformation($"Pushing Events to Azure Blob on storage account :-{CloudConfigurationManager.GetSetting("AzureWebJobsStorage")}");

            IActionResult actionResult = null;

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

            var command = await _commandMapper.Map(requestBody);

            if (_commandValidator.Validate(req, command, ref actionResult))
            {
                switch (command.EventType)
                {
                    case EventType.CARD_BLOCK:
                        _cardBlockCommandHandler.Handle(command as CardBlockCommand);
                        break;
                    case EventType.CARD_CANCEL:
                        _cardCancelledCommandHandler.Handle(command as CardCancelledCommand);
                        break;
                    case EventType.CARD_UNBLOCK:
                        _cardUnBlockHandler.Handle(command as CardUnBlockCommand);
                        break;

                }
                //TODO
                return actionResult;
            }

还有什么更好的方法来避免这种切换情况?

命令处理程序:

public class CardBlockCommandHandler : ICommandHandler<CardBlockCommand>
    {
        private readonly IAzureBlobStorage _azureBlobStorage;

        public CardBlockCommandHandler(IAzureBlobStorage azureBlobStorage)
        {
            _azureBlobStorage = azureBlobStorage;
        }

        public void Handle(CardBlockCommand command)
        {
            try
            {
                //TODO: Store into blob
                //_azureBlobStorage.UploadMessageContentAsync(storageConnectionString: string.Empty,
                //    storageContainerName: string.Empty, blobName: string.Empty, content: string.Empty);

                throw new NotImplementedException();
            }
            catch
            {

            }
        }
    }

ICommandHandler:

public interface ICommandHandler<TCommand> where TCommand : ICommand
    {
        /// <summary>
        /// Execute command
        /// </summary>
        /// <param name="command"></param>
        void Handle(TCommand command);
    }

命令:

public abstract class Command : ICommand
    {
        public EventType EventType { get; }
    }

public interface ICommand
    {
        EventType EventType { get;  }
    }
c# design-patterns azure-functions cqrs
1个回答
2
投票

这是关于使用服务的注释中提到的内容的详细说明。有一个ICommandHandlerService作为依赖项注入到您的函数构造函数中(您使用的是DI容器吗?)。该接口将具有以下方法:

void HandleCommand(ICommand command);

ICommandHandlerService的实现在事件类型和CommandHandler之间有一个Dictionary映射,例如

public class CommandHandlerService : ICommandHandlerService 
{
     Dictionary<EventType, ICommandHandler> handlerDictionary = new Dictionary<EventType, ICommandHandler>(); 
//assuming that all your different handlers implement ICommandHandler ?

     public void CommandHandlerService()
     {
        handlerDictionary.Add(EventType.CARD_UNBLOCK, new CardUnBlockCommandHandler());
        handlerDictionary.Add(EventType.CARD_BLOCK, new CardBlockCommandHandler());
        //setup rest of your associations
     }

}

void HandleCommand(ICommand command)
{
    if(!handlerDictionary.ContainsKey(command.EventType))
    {
       //throw suitable exception ?
    } 

    var commandHandler = handlerDictionary[command.EventType];
    commandHandler.Handle(command);
}

您的Azure函数构造函数将由您的DI框架在ICommandHandlerService实例中传递,因此您可以这样称呼:

if (_commandValidator.Validate(req, command, ref actionResult))
{
    commandHandlerService.Handle(command);
}
© www.soinside.com 2019 - 2024. All rights reserved.