Skip to main content
GameDev.net gamedev.net
🔒 Locked

Question about dependency injection...

Started by CDProp Feb 27, 2009 at 2:33 PM 1 replies 600+ views
Original Post
CDProp
CDProp
I am trying my best to follow this principle, because I agree that objects should ask for what they need, through its constructor parameter list, rather than assuming that what it needs has already been created globally somewhere. I see the wisdom in that. However, it seems to be getting a little unwieldy for me. For instance, I am working on my game objects, and I have one type of game object that requires some meshes:

class ShipObject : public RenderableObject
{
	Mesh	m_HullMesh, m_GunsMesh, m_ShieldMesh;

public:

	ShipObject(Mesh hullMesh, Mesh gunsMesh, Mesh shieldMesh);
}


So, as you can see, this requires three meshes: one for the hull of the shit, one for the guns, and one for the shield. So, I have to supply three meshes in the constructor. Now, a Mesh, in turn, requires two things; namely, a Geo* and a Material:

class Mesh
{
	Geo			*m_pGeometry;
	Material	m_Material;

public:

	Mesh(Geo *pGeometry, Material Material) : m_pGeometry(pGeometry), m_Material(Material) {}

	void		Draw(IDirect3DDevice9 *pDevice);
	Material&	GetMaterial() { return m_Material; }
};


As you can see, there is no default constructor, because that would "lie" about what the Mesh needs. If the purpose of the constructor is to construct a usable Mesh, then I will need it to ask for both of those components, plain and simple. So, that means that my ShipObject class either has to ask for 3 Meshes, or it needs to ask for 3 Geo*'s and 3 Materials so that it can construct the Meshes itself. I cannot simply create the Geo*'s and Materials inside the constructor body, because by the time the body of the constructor is executed, the member objects (the Meshes) have already been constructed. Such a thing wouldn't compile unless Mesh has a default constructor, which as I explained, it doesn't. But it gets even more complicated, because I can't make a Material without a MaterialDefinition (which is a struct, and it basically defines what parameters a material can have; there is a 1:1 relationship between material definitions and effect files):

class Material
{
	const MaterialDefinition	*m_pMaterialDef;
	ParamaterBlock				m_Params;

public:

	Material(const MaterialDefinition *pDef);

	static Material m_Cache;

	void			SetEffectParameters();
	ParamaterBlock&	GetParameters() { return m_Params; }

	const MaterialDefinition*	GetMaterialDefinition() { return m_pMaterialDef; }
};


So, even Material itself lacks a default constructor. So, in order to create a ShipObject, I am going to have to do something like this (assuming all materials use the same definition, which may or may not be the case for some objects):

MaterialDefinition matDef;

/* set matDef's data members */

// Hull
Material myHullMaterial(&matDef);
Geo *pMyHullGeo = GetGeo("hull1");
Mesh myHullMesh(pMyHullGeo, myHullMaterial);

// Guns
Material myGunsMaterial(&matDef);
Geo *pMyGunsGeo = GetGeo("guns2");
Mesh myGunsMesh(pMyGunsGeo, myGunsMaterial);

// Shield
Material myShieldMaterial(&matDef);
Geo *pMyShieldGeo = GetGeo("shield1");
Mesh myShieldMesh(pMyShipGeo, myShieldMaterial);

// Object
ShipObject myShipObject(myHullMesh, myGunsMesh, myShieldMesh);


And, of course, all objects passed by reference must persist as long as the new object persists (which isn't a problem in my case; that includes only geo's and material definitions, which I plan on keeping in a hash table somewhere). Is there a better way? If not, I guess I can create some sort of factory or something to encapsulate all of that objects creation code. It's no big deal, it's just that I feel like I'm missing out on something.
Dancin_Fool
Dancin_Fool
How about having another class which constructs meshes? You could pass that into the constructor along with a struct filled with id's correlating to the assets something along these lines

struct ShipConstructionInfo{    std::string hullMesh;    std::string gunMesh;    std::string shieldMesh;    //and so on with identifiers for the materials};//Assume MeshBuilder is defined elsewhereclass ShipObject : public RenderableObject{	Mesh	m_HullMesh, m_GunsMesh, m_ShieldMesh;public:	ShipObject(MeshBuilder *pBuilder, ShipConstructionInfo info)        {               m_HullMesh = pBuilder(info.hullMesh, info.hullMaterial);               m_GunsMesh = pBuilder(info.gunMesh, info.gunMaterial);               m_ShieldMesh = pBuilder(info.shieldMesh, info.shieldMaterial);        }};
CDProp
CDProp
Hmmm, that is an interesting idea. I'll give it some thought.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.