DI component container, alebo ako volat rozne factory v tovarnicke

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
duskohu
Člen | 778
+
0
-

Caute, hladam nejake rozumne riesenie, mam covarnicku a v nej potrebujem vytvorit stale innu komponentu.
Uvazoval som ci by sa nedalo urobit nieco ako DI component container.
A potom by som mal zaregistrovane x factory a mali by tag, a na zaklade tochto tagu by som si tieto factory volal z MenuComponentContainer, ktory by to vytiahol z DI.

	protected function createComponentMenuItemForm(MenuComponentContainer $menuComponentConainer) {
		return new Multiplier(
			function ($componentTagName) use ($menuComponentConainer) {

				$factory = $menuComponentConainer->getFactory($componentTagName);
				$control = $factory->create();

				return $control;
			}
		);
	}
		$builder->addDefinition($this->prefix('menuItemFormControl'))
			->setImplement(IMenuItemFormControlFactory::class)
			->setFactory(MenuItemFormControl::class)
			->setAutowired(TRUE)
			->setInject(TRUE)
			->addTag('menu.form', 'base-menu');

problem je v tom ze neviem ako to cisto implementovat voci API $control = $factory->create(), kedze kazdy control ma svoj Interface. Alebo nenapada niekoho nejake ciste rozumne riesenie, ako volat rozne factory v createComponent

CZechBoY
Člen | 3608
+
+1
-

Tak potřebuješ nějakej resolver, kterej se rozhodne jakou factory použít. Tomu resolveru bych dal normálně celej kontejner na základě parametru by vytvořil komponentu pomocí některé factory. Já bych i ten resolver navenek pojmenoval factory, protože bude vytvářet a ne jen řešit kterou factory použít.

Konkrétně nevim jakej problém řešíš takže těžko radit jiný řešení než jaký máš vymyšlený. Pokud to jsou položky menu tak jim třeba dát implementovat interface nebo dědit společnou třídu (oboje pak dohledáš v DIC stejně jako tagem).

A ještě bych schoval úplně tu logiku vytváření do té továrny.

protected function createComponentMenuItemForm(MenuComponentFactory $menuComponentFactory) {
    return new Multiplier(
        function ($componentTagName) use ($menuComponentConainer) {
			return $menuComponentFactory->createControl($componentTagName);
        }
    );
}
class MenuComponentFactory
{
	public function __construct(DIContainer $container)
	{
		$this->container = $container;
	}

	public function createControl($tag, array $parameters = [])
	{
		$factory = $this->getFactoryByTag($tag);

		return call_user_func_array([$factory, 'create'], $parameters);
	}
	private function getFactoryByTag($tag)
	{
		// nebo jiná logika
		$serviceNames = $this->container->findByTag($tag);

		$servicesFound = count($serviceNames);

		if ($servicesFoun === 1) {
			return $this->container->getService(reset($serviceNames));
		}

		throw new \Exception('Found ' . $servicesCount . ' with tag ' . $tag . ', expected 1.);
	}
}

Editoval CZechBoY (6. 4. 2017 15:43)

duskohu
Člen | 778
+
0
-

@CZechBoY Vdaka, hned to idem skusit, toto riesenie sa mi paci.