class MethodAccessImpl implements MethodAccess {

    @Override
    public Object invokeDynamic(final Object object, final Object... args) {

        final Class<?>[] parameterTypes = parameterTypes();
        final int paramLength = method.getParameterCount();
        final int argsLength = args.length;


            /* If there are no parameters, just invoke it. */
        if (paramLength == 0) {
            return invoke(object);
        }

        if (paramLength == argsLength) {
            Object[] newArgs = new Object[argsLength];
            for (int index = 0; index < argsLength; index++) {
                final Object arg = args[index];
                final MethodParamAccess methodParamAccess = methodParamList.get(index);
                switch (methodParamAccess.typeEnum()) {
                    case SET:
                        if (arg instanceof Collection) {
                            Collection<Object> argCollection = ((Collection<Object>) arg);
                            newArgs[index] = argCollection.stream().map((Function<Object, Object>) original -> Conversions.coerce(methodParamAccess.componentType(),
                                    methodParamAccess.getComponentClass(), original)).collect(Collectors.toSet());

                        }
                        break;
                    case LIST:
                        if (arg instanceof Collection) {
                            Collection<Object> argCollection = ((Collection) arg);
                            newArgs[index] = argCollection.stream().map((Function<Object, Object>) original -> Conversions.coerce(methodParamAccess.componentType(),
                                    methodParamAccess.getComponentClass(), original)).collect(Collectors.toList());
                        }
                        break;
                    case MAP:
                        if (arg instanceof Map) {
                            Map<Object, Object> argMap = ((Map) arg);
                            Map<Object, Object> convertedMap = new HashMap<>(argMap.size());
                            argMap.forEach((oKey, oValue) -> {
                                Object newKey = Conversions.coerce(methodParamAccess.componentKeyType(),
                                        methodParamAccess.getComponentKeyClass(), oKey);


                                Object newValue = Conversions.coerce(methodParamAccess.componentValueType(),
                                        methodParamAccess.getComponentValueClass(), oValue);

                                convertedMap.put(newKey, newValue);
                            });
                            newArgs[index] = convertedMap;
                        }
                        break;
                    case INSTANCE:
                        newArgs[index] = Conversions.coerce(methodParamAccess.typeEnum(), methodParamAccess.getType(), arg);
                        break;
                    default:
                        if (!methodParamAccess.getType().isInstance(arg)) {
                            TypeType type = paramTypeEnumList.get(index);
                            newArgs[index] = Conversions.coerce(type, methodParamAccess.getType(), arg);
                        } else {
                            newArgs[index] = arg;
                        }

                }
            }
            return this.invoke(object, newArgs);
        } else {
            if (method.isVarArgs() && paramLength == 1) {
                return this.invoke(object, (Object) args);
            } else {
                return Invoker.invokeOverloadedFromList(object, name(), Lists.list(args));
            }
        }
    }

    public  MethodAccessImpl();
    public  MethodAccessImpl(Method method);

}