protected virtual void AssertReturnTypeCombination(MethodInfo adapterMethod, MethodInfo targetMethod, InvocationTypes targetInvocationType)
        {
            Type targetMethodReturnType = targetMethod.ReturnType;

            switch (targetInvocationType)
            {
            case InvocationTypes.Sync:
                if (AdapterHelper.IsVoid(adapterMethod.ReturnType) && adapterMethod.ReturnType != targetMethodReturnType)
                {
                    throw new AdapterInterceptorException($"Adapter and target method return types should match if either is void.{Environment.NewLine}Adapter method: {adapterMethod.ToLoggerString()}{Environment.NewLine}Target method: {targetMethod.ToLoggerString()}");
                }
                break;

            case InvocationTypes.GenericTask:
                if (!AdapterHelper.IsGenericTask(adapterMethod.ReturnType))
                {
                    throw new AdapterInterceptorException($"Adapter and target method return types should both be a generic Task.{Environment.NewLine}Adapter method: {adapterMethod.ToLoggerString()}{Environment.NewLine}Target method: {targetMethod.ToLoggerString()}");
                }
                break;

            case InvocationTypes.Task:
                if (adapterMethod.ReturnType != targetMethodReturnType)
                {
                    throw new AdapterInterceptorException($"Adapter and target method return types should match if target return type is Task.{Environment.NewLine}Adapter method: {adapterMethod.ToLoggerString()}{Environment.NewLine}Target method: {targetMethod.ToLoggerString()}");
                }
                break;

            case InvocationTypes.GenericValueTask:
                if (!AdapterHelper.IsGenericValueTask(adapterMethod.ReturnType))
                {
                    throw new AdapterInterceptorException($"Adapter and target method return types should both be a generic ValueTask.{Environment.NewLine}Adapter method: {adapterMethod.ToLoggerString()}{Environment.NewLine}Target method: {targetMethod.ToLoggerString()}");
                }
                break;

            case InvocationTypes.ValueTask:
                if (!AdapterHelper.IsValueTask(adapterMethod.ReturnType))
                {
                    throw new AdapterInterceptorException($"Adapter and target method return types should match if target return type is ValueTask.{Environment.NewLine}Adapter method: {adapterMethod.ToLoggerString()}{Environment.NewLine}Target method: {targetMethod.ToLoggerString()}");
                }
                break;

            default: throw new NotImplementedException();
            }
        }
        protected virtual AdapterInvocationInformation PrepareAdapterInvocationInformation(MethodInfo adapterMethod, MethodInfo targetMethod, Type[] adapterMethodParameterTypes, Type[] targetMethodParmeterTypes)
        {
            Type targetMethodReturnType = targetMethod.ReturnType;

            // Task<>
            if (AdapterHelper.IsGenericTask(targetMethodReturnType))
            {
                MethodInfo      genericInvokeTargetGenericTaskAsyncMethod = _invokeTargetGenericTaskAsync_Method.MakeGenericMethod(adapterMethod.ReturnType.GenericTypeArguments[0]);
                InvocationTypes targetInvocationType = InvocationTypes.GenericTask;
                AssertReturnTypeCombination(adapterMethod, targetMethod, targetInvocationType);
                return(new AdapterInvocationInformation(targetMethod, adapterMethodParameterTypes, targetMethodParmeterTypes, targetInvocationType, genericInvokeTargetGenericTaskAsyncMethod));
            }
            // Task
            else if (AdapterHelper.IsTask(targetMethodReturnType))
            {
                InvocationTypes targetInvocationType = InvocationTypes.Task;
                AssertReturnTypeCombination(adapterMethod, targetMethod, targetInvocationType);
                return(new AdapterInvocationInformation(targetMethod, adapterMethodParameterTypes, targetMethodParmeterTypes, targetInvocationType));
            }
            // ValueTask<>
            else if (AdapterHelper.IsGenericValueTask(targetMethodReturnType))
            {
                MethodInfo      genericInvokeTargetGenericValueTaskAsyncMethod = _invokeTargetGenericValueTaskAsync_Method.MakeGenericMethod(adapterMethod.ReturnType.GenericTypeArguments[0]);
                InvocationTypes targetInvocationType = InvocationTypes.GenericValueTask;
                AssertReturnTypeCombination(adapterMethod, targetMethod, targetInvocationType);
                return(new AdapterInvocationInformation(targetMethod, adapterMethodParameterTypes, targetMethodParmeterTypes, targetInvocationType, genericInvokeTargetGenericValueTaskAsyncMethod));
            }
            // ValueTask
            else if (AdapterHelper.IsValueTask(targetMethodReturnType))
            {
                InvocationTypes targetInvocationType = InvocationTypes.ValueTask;
                AssertReturnTypeCombination(adapterMethod, targetMethod, targetInvocationType);
                return(new AdapterInvocationInformation(targetMethod, adapterMethodParameterTypes, targetMethodParmeterTypes, targetInvocationType));
            }
            else
            // Likely synchronous
            {
                InvocationTypes targetInvocationType = InvocationTypes.Sync;
                AssertReturnTypeCombination(adapterMethod, targetMethod, targetInvocationType);
                return(new AdapterInvocationInformation(targetMethod, adapterMethodParameterTypes, targetMethodParmeterTypes, targetInvocationType));
            }
        }