InterfaceBinder.h
// InterfaceBinder.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2015
@import "IObject.h"
#include <functional>
/*
This is a mechanism for allowing objects to implement interfaces "a posteriori".
For example this is useful for a clean separation between data and its visualisation.
Persistent objects defined in libraries can be defined without any code for the visualisation.
allowing the library to be small and simple, in turn allowing a GUI-less server to be small,
simple, robust and efficient.
This interface binder registry can be used to allow the objects to implement interfaces "after the
fact" as it were, such as a view creation method.
*/
namespace ceda
{
typedef std::function<AnyInterface(void*)> BindInterfaceFn;
// There is a global registry which allows for registering a BindInterfaceFn for a given (rc,ri)
// pair
// Returns false if a BindInterfaceFn for the given (rc,ri) pair has already been registered.
@api bool RegisterLateInterfaceBinder(const ReflectedClass& rc, const ReflectedInterface& ri, BindInterfaceFn bindFn);
// Use the interface binder registry to bind to interface 'ri' for object of type 'rc' at address
//'pObj'. pObj must not be null. Returns null if no binder for the given (rc,ri) pair has been
// registered.
@api AnyInterface LateBindInterface(const ReflectedClass& rc, const ReflectedInterface& ri, void* pObj);
template<typename I>
ptr<I> LateBindInterface(ptr<IObject> obj)
{
cxAssert(obj);
const ReflectedClass* rc = obj->GetReflectedClass();
cxAssert(rc);
auto p = LateBindInterface( *rc, GetReflectedInterface<I>(), obj );
return reinterpret_cast<ptr<I>&>(p);
}
template<typename I, typename C>
ptr<I> LateBindInterface(C* obj)
{
cxAssert(obj);
auto p = LateBindInterface( GetReflectedClass<C>(), GetReflectedInterface<I>(), obj );
return reinterpret_cast<ptr<I>&>(p);
}
} // namespace ceda