Skip to content

Commit

Permalink
Refactor for simplicity.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Carroll committed Sep 10, 2012
1 parent bcf8037 commit 4c927b7
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 180 deletions.
3 changes: 3 additions & 0 deletions Exception.h
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include "StdString.h"
#include <iostream>

#define YAUL_COPYVARARGS(fmt) va_list argList; va_start(argList, fmt); set(fmt, argList); va_end(argList)
#define YAUL_STANDARD_EXCEPTION(E) \
Expand Down Expand Up @@ -46,6 +47,7 @@ namespace YaulCommons
CStdString tmps;
tmps.FormatV(fmt, argList);
message = tmps;
std::cout << "EXCEPTION:" << getExceptionType() << ":" << getMessage() << std::endl;
}

/**
Expand All @@ -60,6 +62,7 @@ namespace YaulCommons

public:
inline const char* getMessage() const { return message.c_str(); }
inline const char* getExceptionType() const { return classname.c_str(); }
};
}

65 changes: 14 additions & 51 deletions di.cpp
Expand Up @@ -12,16 +12,6 @@ namespace di
{
namespace internal
{
const std::string RequirementBase::toString() const
{
CStdString msg;
if (specifiesId)
msg.Format("(%s requires %s with id %s)",instance.getTypeInfo().name(), parameter.getTypeInfo().name(), requiredId.c_str());
else
msg.Format("(%s requires %s)",instance.getTypeInfo().name(), parameter.getTypeInfo().name());
return msg;
}

void* InstanceBase::convertTo(const TypeBase& typeToConvertTo) const throw (DependencyInjectionException)
{
const void* obj = getConcrete();
Expand All @@ -41,7 +31,7 @@ namespace di
return NULL;
}

bool InstanceBase::canConvertTo(const TypeBase& typeToConvertTo) const
bool InstanceBase::canConvertTo(const internal::TypeBase& typeToConvertTo) const
{
for(std::vector<TypeConverterBase*>::const_iterator it = providesTheseTypes.begin(); it != providesTheseTypes.end(); it++)
{
Expand All @@ -55,28 +45,31 @@ namespace di
}
}

internal::InstanceBase* Context::find(const std::type_info& typeInfo)
internal::InstanceBase* Context::find(const internal::TypeBase& typeInfo, const char* id, bool exact)
{
for(std::vector<internal::InstanceBase*>::iterator it = instances.begin(); it != instances.end(); it++)
{
internal::InstanceBase* instance = (*it);

if (instance->type.getTypeInfo() == typeInfo)
if (((exact && instance->type.getTypeInfo() == typeInfo.getTypeInfo()) ||
(!exact && instance->canConvertTo(typeInfo))) &&
(id == NULL || instance->id == id))
return instance;
}
return NULL;
}

internal::InstanceBase* Context::find(const char* id, const std::type_info& typeInfo)
void Context::findAll(std::vector<internal::InstanceBase*>& ret, const internal::TypeBase& typeInfo, const char* id, bool exact)
{
for(std::vector<internal::InstanceBase*>::iterator it = instances.begin(); it != instances.end(); it++)
{
internal::InstanceBase* instance = (*it);

if (instance->type.getTypeInfo() == typeInfo && instance->id == id)
return instance;
if (((exact && instance->type.getTypeInfo() == typeInfo.getTypeInfo()) ||
(!exact && instance->canConvertTo(typeInfo))) &&
(id == NULL || instance->id == id))
ret.push_back(instance);
}
return NULL;
}

void Context::resetInstances()
Expand Down Expand Up @@ -126,9 +119,10 @@ namespace di
}
}

// clear out the instances.
resetInstances();
}

// clear out the instances.
resetInstances();
}

void Context::clear()
Expand Down Expand Up @@ -199,38 +193,7 @@ namespace di
for (std::vector<internal::RequirementBase*>::iterator rit = requirements.begin(); rit != requirements.end(); rit++)
{
internal::RequirementBase* requirement = (*rit);

// now go through all of the instances and see which one satisfies
// the requirements. Make sure that no more than one does.
std::vector<internal::InstanceBase*> satisfies;

for(std::vector<internal::InstanceBase*>::iterator it2 = instances.begin(); it2 != instances.end(); it2++)
{
internal::InstanceBase* comp = (*it2);

if (requirement->isSatisfiedBy(comp))
satisfies.push_back(comp);
}

if (satisfies.size() < 1)
{
resetInstances();
throw DependencyInjectionException("Cannot satisfy the requirement of \"%s\" which requires \"%s\".", instance->toString().c_str(), requirement->toString().c_str());
}
else if (!requirement->satisfiedWithSet() && satisfies.size() > 1)
{
resetInstances();
throw DependencyInjectionException("Ambiguous requirement of \"%s\" for \"%s\".", instance->toString().c_str(), requirement->toString().c_str());
}

// ok then, we need to plug in the dependency
if (requirement->satisfiedWithSet())
requirement->satisfyWithSet(satisfies);
else
{
internal::InstanceBase* dep = satisfies.front();
requirement->satisfyWith(dep);
}
requirement->satisfy(instance,this);
}
}

Expand Down
59 changes: 19 additions & 40 deletions di.h
Expand Up @@ -226,10 +226,9 @@ namespace di
*/
template <class T> class Type : public internal::TypeBase
{
const char* objId;
public:
inline Type() : internal::TypeBase(typeid(T)), objId(NULL) {}
inline Type(const char* id) : internal::TypeBase(typeid(T)), objId(id) {}
inline Type() : internal::TypeBase(typeid(T)) {}
inline Type(const char* id) : internal::TypeBase(id,typeid(T)) {}
virtual ~Type() {}

/**
Expand All @@ -250,11 +249,9 @@ namespace di

typedef T* type;

inline T* find(Context* context) const throw (DependencyInjectionException);
inline T* findProvides(Context* context) const throw (DependencyInjectionException);
inline bool available(Context* context) const;

inline const char* getId() const { return objId; }
};
};

/**
* A Constant value can be supplied to satisfy constructor requirements during
Expand All @@ -270,10 +267,13 @@ namespace di
inline Constant(T val) : instance(val) {}
inline Constant(const Constant& o) : instance(o.instance) {}

inline const T& find(Context* context) { return instance; }
inline const T& findProvides(Context* context) { return instance; }
inline bool available(Context* context) { return true; }
};

// Nothing to see here, move along ...
#include "internal/direquirement.h"

/**
* This template allows the declaration of object instances in a context.
*/
Expand Down Expand Up @@ -339,19 +339,19 @@ namespace di
* dependency. Using a Ref you can alternatively supply a name for the
* object that this instance requires.
*/
template<typename D> inline Instance<T>& requires(const Type<D>& dependency, typename internal::Requirement<T,D>::Setter setter)
template<typename D> inline Instance<T>& requires(const Type<D>& dependency, typename internal::Setter<T,D*>::type setter)
{
requirements.push_back(new internal::Requirement<T,D>(dependency.getId(), this,setter));
requirements.push_back(new internal::Requirement<T,D>(dependency,setter));
return *this;
}

/**
* Use this method to declare that this instance requires a particular
* dependency.
*/
template<typename D> inline Instance<T>& requiresAll(const Type<D>& dependency, typename internal::Requirement<T,D>::SetterAll setter)
template<typename D> inline Instance<T>& requiresAll(const Type<D>& dependency, typename internal::SetterAll<T,D*>::type setter)
{
requirements.push_back(new internal::Requirement<T,D>(this,setter));
requirements.push_back(new internal::RequirementAll<T,D>(dependency,setter));
return *this;
}

Expand Down Expand Up @@ -385,7 +385,6 @@ namespace di
* Returns the underlying instance.
*/
inline T* get() { return (T*)getConcrete(); }

};

// Still nothing to see here, move along ...
Expand All @@ -410,8 +409,9 @@ namespace di

public:

internal::InstanceBase* find(const std::type_info& typeInfo);
internal::InstanceBase* find(const char* id, const std::type_info& typeInfo);
internal::InstanceBase* find(const internal::TypeBase& typeInfo,const char* id = NULL, bool exact = true);

void findAll(std::vector<internal::InstanceBase*>& ret, const internal::TypeBase& typeInfo,const char* id = NULL, bool exact = true);

virtual ~Context() { clear(); }

Expand Down Expand Up @@ -557,26 +557,14 @@ namespace di
*/
void clear();

/**
* Allows retrieving an object by its type. If there is more than
* one instance that is of this type, it will simply return the
* first one it finds in the context.
*/
template<typename T> T* get(Type<T> typeToFind)
{
internal::InstanceBase* ret = find(typeToFind.getTypeInfo());

return ret != NULL ? ((Instance<T>*)ret)->get() : NULL;
}

/**
* Allows retrieving an object by its type and Id. If there is more than
* one instance that is of this type, it will simply return the
* first one it finds in the context.
*/
template<typename T> T* get(const char* id, Type<T> typeToFind)
template<typename T> T* get(const Type<T>& typeToFind, const char* id = NULL)
{
internal::InstanceBase* ret = find(id,typeToFind.getTypeInfo());
internal::InstanceBase* ret = find(typeToFind,id);

return ret != NULL ? ((Instance<T>*)ret)->get() : NULL;
}
Expand All @@ -593,17 +581,8 @@ namespace di
inline bool isStarted() { return curPhase == started; }
};

template<typename T> inline T* Type<T>::find(Context* context) const throw (DependencyInjectionException)
{
internal::InstanceBase* ip1 = (objId == NULL ? context->find(this->getTypeInfo()) : context->find(objId,this->getTypeInfo()));
return (type)ip1->convertTo(*this);
}

template<typename T> inline bool Type<T>::available(Context* context) const
{
internal::InstanceBase* inst = (objId == NULL ? context->find(this->getTypeInfo()) : context->find(objId,this->getTypeInfo()));
return inst != NULL && inst->instantiated();
}
// Nothing to see here, move along ...
#include "internal/diimpl.h"

}

Expand Down

0 comments on commit 4c927b7

Please sign in to comment.