@Override
  public Statement getBeanInstance(final InjectableInstance injectableInstance) {
    final MetaClass type;
    final MetaParameterizedType pType;

    switch (injectableInstance.getTaskType()) {
      case Type:
        return null;
      case PrivateField:
      case Field:
        final MetaField field = injectableInstance.getField();
        type = field.getType();

        pType = type.getParameterizedType();
        break;

      case Parameter:
        final MetaParameter parm = injectableInstance.getParm();
        type = parm.getType();

        pType = type.getParameterizedType();
        break;

      default:
        throw new RuntimeException("illegal task type: " + injectableInstance.getEnclosingType());
    }

    final MetaType[] typeArgs = pType.getTypeParameters();
    final MetaClass[] typeArgsClasses = new MetaClass[typeArgs.length];

    for (int i = 0; i < typeArgs.length; i++) {
      final MetaType argType = typeArgs[i];

      if (argType instanceof MetaClass) {
        typeArgsClasses[i] = (MetaClass) argType;
      } else if (argType instanceof MetaParameterizedType) {
        typeArgsClasses[i] = (MetaClass) ((MetaParameterizedType) argType).getRawType();
      }
    }

    final Annotation[] qualifiers = injectableInstance.getQualifiers();

    final BlockBuilder<?> block =
        injectableInstance.getInjectionContext().getProcessingContext().getBlockBuilder();
    final MetaClass providerCreationalCallback =
        MetaClassFactory.parameterizedAs(
            CreationalCallback.class,
            MetaClassFactory.typeParametersOf(providerInjector.getInjectedType()));

    final String varName =
        InjectUtil.getVarNameFromType(
            providerInjector.getConcreteInjectedType(), injectableInstance);

    final Statement valueRef;

    if (providerInjector.isSingleton() && providerInjector.isRendered()) {
      valueRef =
          Stmt.loadVariable("beanInstance")
              .invoke("provide", typeArgsClasses, qualifiers.length != 0 ? qualifiers : null);
    } else {

      valueRef = Stmt.load(null);
    }

    block.append(
        Stmt.declareFinalVariable(
            varName,
            providerCreationalCallback,
            Stmt.newObject(providerCreationalCallback)
                .extend()
                .publicOverridesMethod(
                    "callback", Parameter.of(providerInjector.getInjectedType(), "beanInstance"))
                .append(
                    Stmt.loadVariable(InjectUtil.getVarNameFromType(type, injectableInstance))
                        .invoke("callback", valueRef))
                .append(Stmt.loadVariable("async").invoke("finish", Refs.get("this")))
                .finish()
                .publicOverridesMethod("toString")
                .append(
                    Stmt.load(providerInjector.getInjectedType()).invoke("getName").returnValue())
                .finish()
                .finish()));

    block.append(Stmt.loadVariable("async").invoke("wait", Refs.get(varName)));

    block.append(
        Stmt.loadVariable(providerInjector.getCreationalCallbackVarName())
            .invoke("getInstance", Refs.get(varName), Refs.get("context")));

    return null;
  }
 @Override
 public void renderProvider(InjectableInstance injectableInstance) {
   providerInjector.renderProvider(injectableInstance);
 }