public async Task CanExecuteTaskAsync()
        {
            var type = typeof(VoidValueTaskExecutorClassTest);

            var method = type.GetMethod(nameof(VoidValueTaskExecutorClassTest.TestMethod));

            await using var context = new CommandContext();

            var moduleBuilderMock = new Mock <IModuleBuilder>();

            moduleBuilderMock.SetupGet(a => a.Type).Returns(type);

            var commandBuilderMock = new Mock <ICommandBuilder>();

            commandBuilderMock.SetupGet(a => a.IsAsync).Returns(true);
            commandBuilderMock.SetupGet(a => a.MethodInfo).Returns(method);

            var moduleBuilder  = moduleBuilderMock.Object;
            var commandBuilder = commandBuilderMock.Object;

            var executor = VoidValueTaskExecutor.Create(moduleBuilder, commandBuilder);

            var module = new VoidValueTaskExecutorClassTest();

            (module as IModuleBase).SetContext(context);

            var result = await executor.ExecuteAsync(module, new object[0]);

            Assert.NotNull(result);
            Assert.True(result.Success);
            Assert.IsType <SuccessResult>(result);
            Assert.NotEmpty(context.Items);
            Assert.True(context.Items.ContainsKey(VoidValueTaskExecutorClassTest.LogKey));
            Assert.Equal(VoidValueTaskExecutorClassTest.LogValue, context.Items[VoidValueTaskExecutorClassTest.LogKey]);
        }
        public ICommandExecutor GetCommandExecutor(IModuleBuilder moduleBuilder, ICommandBuilder commandBuilder)
        {
            var type            = commandBuilder.MethodInfo.ReturnType;
            var asyncResultType = commandBuilder.AsyncResultType;

            if (commandBuilder.IsAsync)
            {
                if (type == typeof(Task) && commandBuilder.AsyncResultType.HasNoContent())
                {
                    return(VoidTaskExecutor.Create(moduleBuilder, commandBuilder));
                }

                if (type == typeof(ValueTask) && commandBuilder.AsyncResultType.HasNoContent())
                {
                    return(VoidValueTaskExecutor.Create(moduleBuilder, commandBuilder));
                }

                var genericDefinition = type.GetGenericTypeDefinition();

                if (genericDefinition == typeof(Task <>) && typeof(IResult).IsAssignableFrom(asyncResultType))
                {
                    return(ResultTaskExecutor.Create(moduleBuilder, commandBuilder));
                }

                if (genericDefinition == typeof(ValueTask <>) && typeof(IResult).IsAssignableFrom(asyncResultType))
                {
                    return(ResultValueTaskExecutor.Create(moduleBuilder, commandBuilder));
                }

                if (genericDefinition == typeof(ValueTask <>))
                {
                    return(ObjectValueTaskExecutor.Create(moduleBuilder, commandBuilder));
                }

                return(ObjectTaskExecutor.Create(moduleBuilder, commandBuilder));
            }

            if (type == typeof(void))
            {
                return(VoidExecutor.Create(moduleBuilder, commandBuilder));
            }

            if (typeof(IResult).IsAssignableFrom(type))
            {
                return(ResultExecutor.Create(moduleBuilder, commandBuilder));
            }

            return(ObjectExecutor.Create(moduleBuilder, commandBuilder));
        }