Auflösen Variadics Package-Packing als Konstruktor Argument

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
snoob741
Beiträge: 76
Registriert: 03.04.2012, 22:36

Auflösen Variadics Package-Packing als Konstruktor Argument

Beitrag von snoob741 »

Aktuell versuche ich mein IOCContainer zu erweitern um bei der Registrierung auch Abhängigkeiten zu berücksichtigen. Das klappt auch schon wie gewünscht für den Fall, dass die Abhängigkeiten über den Typen direkt aufgelöst werden können. Hiefür habe ich folgendes implementiert:

Code: Alles auswählen

	template <typename T, typename ... D>
	void wire(void)
	{
		std::type_index type = typeid(T);
	
		auto iter = m_repository.begin();
		while(iter!=m_repository.end()){			
			if((iter->first) == type ||
			   (iter->second)->getType() == type){
				break;
			}
			iter++;
		}
			
		auto delegate = [this]() -> T * {
            return new T(this->resolve<D>()...);
        };
		
		auto component = iter->second;
		component->setResolver(std::shared_ptr<Resolver>(new DelegateResolver<T>(delegate, this)));
	}
T definiert hierbei den konkreten, transienten Typen der erzeugt werden soll und D die Abhängigkeiten
als Variadics. Das ganze läuft bestens, sofern ich die Abhängigkeiten immer über den Typen auflösen
kann, die ich zuvor registriert habe. Hier mal mein Google-Test Snipped hierzu:

Code: Alles auswählen

TEST(brIOCContainerTest, wire) 
{
	brIOCContainer container;
	container.registerType<Armament>();
	
	container.registerByContract<Rifle, Gun>();
	container.registerByContract<GrenadeLauncher, Gun>();
		
	container.wire<Armament, Rifle, GrenadeLauncher>();	
	
	auto r1 = container.resolve<Armament>();
	ASSERT_NE(nullptr, r1.get());
	ASSERT_NE(nullptr, r1->getPrimaryWeapon().get());
	ASSERT_NE(nullptr, r1->getSecondaryWeapon().get());
	ASSERT_NE(r1->getPrimaryWeapon(), r1->getSecondaryWeapon());
}
Ich habe jedoch auch die Möglichkeit, mehrere Implementationen eines Typens zu registrieren und über den Namen aufzulösen um mehrere Instanzen eines Typs zu registrieren (z.B. verschiedene Logger, die lediglich verschiedene Logfiles als Output haben). Das klappt auch für den angeforderten Objekttypen, muss jedoch auch bei den Abhängikeiten berücksichtigt werden (wenn diese injected werden sollen).

Und genau hier ist der Kasus-Knacksus. Irgendwie sehe ich aktuell keine Möglichkeit dies zu realisiern. Das Problem ist der Lambada Ausdruck zum Erzeugen der konkreten Instanz:

Code: Alles auswählen

auto delegate = [this]() -> T * {
        return new T(this->resolve<D>()...);
};
Hier müsste ich irgendwie beim Resolve die Möglichkeit haben, pro Aufruf einen Parameter mit zu geben, der dann ausgewertet wird. Zunächst habe ich gedacht, ich nutze ein Template für die Dependency, das verschiedene Parameter beim Auflösen berücksichtigt und an die resolve-Methode als Parameter mit übergeben wird:

Code: Alles auswählen

	template <typename D> 
	void resolve(const D& dependency) {}
Das Template lässt sich leicht realisieren, jedoch habe ich keine Idee, wie ich dies übergeben bekomme. Eigentlich müsste ich das Parameter Packing Packing hier auflösen, dafür kenne ich nur den rekursiven Ansatz, der mir hier nichts bringt da ich die Rückgabewerte nicht "sammeln" kann ...

Hatte daher auch gedacht ich könnte evtl. aus dem Variadic Parameter-Packing eine Initializer-Liste aufbauen und die übergeben. Aber auch das geht nicht, da diese soweit ich das gesehen habe, keine unterschiedlichen Datentypen erlaubt ...

Hat jemand von Euch eine Idee wie man das Problem lösen kann? Ist es überhaupt möglich?
Antworten