auraphp / Aura.Di

Dependency Injection System
MIT License
349 stars 63 forks source link

Include "ResolutionHelper" ala Radar\Adr\Resolver ? #133

Closed jakejohns closed 7 years ago

jakejohns commented 8 years ago

I might be overly excited by the way Radar/Arbiter use the Resolver, but I find my self wanting to imitate it from time to time. ie. Having an object which takes a callable that can resolve an object from a 'spec'. I might be tying my objects to the container too much in this, but it seems nice in various places.

At any rate, when doing this, I find myself creating essentially the same code for the Resolver every time. Or rather, I end up making a package with no dependency on Aura/DI, but has an object which takes a callable "$resolver", and then elsewhere making a the bridge to Aura/Di which has the actual Resolver code, lifted from Radar.

Would it make sense to simply include the wrapper for the InjectionFactory in Aura\Di?

<?php
/**
 *
 * This file is part of Aura for PHP.
 *
 * @license http://opensource.org/licenses/MIT MIT
 *
 */
namespace Aura\Di;

use Aura\Di\Injection\InjectionFactory;

/**
 *
 * Resolves object specifications using the DI container.
 *
 * @package aura/di
 *
 */
class ResolutionHelper
{
    /**
     *
     * The injection factory from the DI container.
     *
     * @var InjectionFactory
     *
     */
    protected $injectionFactory;

    /**
     *
     * Constructor.
     *
     * @param InjectionFactory $injectionFactory The injection factory from the
     * DI container.
     *
     */
    public function __construct(InjectionFactory $injectionFactory)
    {
        $this->injectionFactory = $injectionFactory;
    }

    /**
     *
     * Resolves an object specification.
     *
     * @param mixed $spec The object specification.
     *
     * @return mixed
     *
     */
    public function __invoke($spec)
    {
        if (is_string($spec)) {
            return $this->injectionFactory->newInstance($spec);
        }

        if (is_array($spec) && is_string($spec[0])) {
            $spec[0] = $this->injectionFactory->newInstance($spec[0]);
        }

        return $spec;
    }
}

Thoughts? Is my fetish of this paradigm in fact an acrid code stench?

I didn't PR cuz, I'm a little iffy on this, and additionally am not sure where it the package it should go, and if the container should just have a method to get it like the InjectionFactory itself. Having $di->getResolutionHelper() in addition to $di->getInjectionFactory() seemed off to me.

Perhaps the InjectionFactory itself just be given the __invoke method and be made callable?

class InjectionFactory
{
    // ...

    public function __invoke($spec)
    {
        if (is_string($spec)) {
            return $this->newInstance($spec);
        }

        if (is_array($spec) && is_string($spec[0])) {
            $spec[0] = $this->newInstance($spec[0]);
        }

        return $spec;
    }
}

The part that seems weird to me here is that the bit about arrays seems to imply that its really for resolving callables, but I kind of like it cuz works for what I want often.

Thoughts?

pmjones commented 7 years ago

I'm fine with something like this. Send a PR against the 3.x branch if you're still interested; or, if not, close the issue at will. :-)