public async Task <string> Create(string title, int amount)
        {
            var product = new Product
            {
                Id     = Guid.NewGuid().ToString(),
                Title  = title,
                Amount = amount,
            };
            var @event = await CreateEvent(
                product.Id, EventTypes.ProductCreated, product);

            var productCreated = ProductCreated.Create(@event, product);

            messageQueue.Publish(productCreated);
            return(product.Id);
        }
        IMessage <object> ConstructMessage <T>(Event @event)
        {
            var data = @event.Data;

            if (data == null)
            {
                throw new ArgumentNullException(nameof(@event.Data));
            }

            switch (data.Type)
            {
            case EventTypes.AmountUpdated:
                var amount = data.Payload as int?;
                if (amount != null)
                {
                    return((IMessage <object>)AmountUpdated.Create(@event, data.Id, amount.Value));
                }
                break;

            case EventTypes.ProductCreated:
                if (data.Payload is Product product)
                {
                    return((IMessage <object>)ProductCreated.Create(@event, product));
                }
                break;

            case EventTypes.ProductDeleted:
                return((IMessage <object>)ProductDeleted.Create(@event, data.Id));

            case EventTypes.TitleUpdated:
                var title = data.Payload as string;
                return((IMessage <object>)TitleUpdated.Create(@event, data.Id, title));

            default:
                break;
            }

            throw new ArgumentException($"InvalidEvent data: {data.Id}, " +
                                        $"{data.Type}, {data.Payload}");
        }