How do I create factories capable of multiple parameters with Zenject? - zenject

How do I create a factories with zenject with multiple parameter overloaded Create methods (or how to solve this problem differently)?
I want to be able to
var x = factory.Create("bla bla");//string
x = factory.Create();//parameterless
x = factory.Create(1);//int
x = factory.Create(1,2);//int,int
x = factory.Create("bla bla",2);//string,int

One way would be to create a factory that includes the maximum number of parameters and then supply extra methods that use default values for the missing values like this:
public class Foo
{
[Inject]
public string Value1;
[Inject]
public int Value2;
public class Factory : Factory<string, int, Foo>
{
public Foo Create(string value1)
{
return Create(value1, 0);
}
public Foo Create()
{
return Create("default");
}
}
}

Related

How to make the following multiple inheritance work in C++

The idea is for the users to create a new class and inherit only the base class and few special classes whose special functions they want.
class Base {
Data data;
public:
void init(Data d) data(d) {}
// other basic functions
}
class SpecialX: public Base {
public:
Result specialX() {
Result r = compute(data); // uses Base::data to compute some result
return r;
}
}
class SpecialY: public Base {
public:
Result specialY() {
Result r = compute(data); // uses Base::data to compute some result
return r;
}
}
If user wants only init and specialX functions, they could do something like -
class My: public Base, public SpecialX {} // user doesn't need specialY function, so they do not inherit it
My m;
m.init(someData);
m.specialX(); // returns the result by computing specialX
But this throws the ambiguity error due to the Diamond problem in C++.
How do I structure my classes so that I can create as many special classes as I want, and let users inherit the ones that they need?

Setting value from Derivered class, while accesing same value from base class

I am getting an issue for retrieving BaseClass correct enum value.
class BaseClass
{
public:
enum EntityId {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
void setEntityId(EntityId id) { _Entityid = id; }
EntityId getEntityId() { return _Entityid; }
protected:
EntityId _Entityid;
};
and
class DeriveredClassA : public SomeClass, public BaseClass {....};
class DeriveredClassB : public SomeClass, public BaseClass {....};
The initialization goes like this
DeriveredClassA->setEntityId(BaseClass::EntityId::EN_PLAYER);
DeriveredClassB->setEntityId(BaseClass::EntityId::EN_OBSTACLE);
Which is placed into a different vector list correspoinding to that enum.
However, I am forced to use void* to do static_casts cats...
Like this:
BaseClass* EA = static_cast<BaseClass*>(bodyUserDataA); //bodyUserDataA and bodyUserDataB are both void*
BaseClass* EB = static_cast<BaseClass*>(bodyUserDataB);
And I am trying to retrieve using EA->getEntityId() and EB->getEntityId() so I could check which one is EN_PLAYER, which one is EN_GROUND and etc. So then I could up-class from base into derivered class and do other stuff with it.
Tried using with virtual, however somehow I am receiving 2 copies of _EntityID, which can be either the same or DIFFERENT between my Derivered and BaseClass of that one object.
Moreover, I can't cast right away into DeriveredClass, since the code checking would be huge, due to many different types of DeriveredClass'es (DeriveredClassA, DeriveredClassB, DeriveredClassC, DeriveredClassD) with their corresponding vector list.
My question is that How I need setup correctly both Base and Derivered class, so that I could access _EntityID from Baseclass which is the same of that DeriveredClass? My main problem might is that I used incorectly virtual functions, so I left on default to understand my issue.
P.S. This is mainly my c++ issue, other tags are added due to I am using game engine and physics engine for this case.
I believe that you want your code to look more like this:
class Entity
{
public:
enum Type {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
Type getType() { return _type; }
protected:
Entity(Type type): _type(type) {}
private:
const Type _type;
};
Then your derived classes and usage of this base would be more like:
class PlayerEntity: public Entity, public SomeClass
{
public:
PlayerEntity(std::string name): Entity(EN_PLAYER), _name(name) {}
std::string getName() const { return _name; }
private:
std::string _name;
};
class PlatformEntity: public Entity, public SomeClass
{
public:
PlatformEntity(): Entity(EN_PLATFORM) {}
};
Initialization is then done like:
int main()
{
PlatformEntity platform;
std::vector<PlatformEntity> platforms(platform);
std::vector<PlayerEntity> players;
players.emplace_back("Bob");
players.emplace_back("Alice");
players.emplace_back("Ook");
}
Access from user-data could then look like this:
// bodyUserDataA and bodyUserDataB are both void*
Entity* const EA = static_cast<Entity*>(bodyUserDataA);
Entity* const EB = static_cast<Entity*>(bodyUserDataB);
switch (EA->getType())
{
case Entity::EN_PLAYER:
{
PlayerEntity* player = static_cast<PlayerEntity*>(EA);
std::cout << "Found player: " << player->getName();
break;
}
case Entity::EN_OTHER:
...
default:
break;
}

What is best way to know type of sender object?

I have hierarchy of classes:
class A
{
};
class B : public A
{
};
class C : public B
{
};
class D : public A
{
};
and I have some function, which performs notification:
void notify(A* sender, const NotificationType notification)
{
}
My problem is how to find out exact type of sender object. I want to find elegant way to solve this problem. I don't like to use dynamic cast for these purposes. Possible way is to define enum within class A like:
enum ClassType
{
CLASS_A,
CLASS_B,
CLASS_C,
CLASS_D
};
and defining virtual method:
virtual ClassType get_type(void) const;
But this approach has bad scalability. Another way to keep this information in NotificationType, but it has bad scalability too.
P.S. I just want to use similar code:
I want to use similar code:
void notify(A* sender, const NotificationType notification)
{
if (sender is object of A)
new GuiA();
else if (sender is object of B)
new GuiB();
else if (sender is object of C)
new GuiC();
else
new GuiD();
}
To create a matching GUI object based on the concrete type of sender, you could pass a factory to some kind of factory method in A.
class A
{
public:
virtual Agui* createGui(GuiFactory& fac) = 0;
};
class GuiFactory
{
public:
virtual Agui* forB(B&) = 0;
virtual Agui* forC(B&) = 0;
virtual Agui* forD(D&) = 0;
};
class B : public A
{
public:
Agui* createGui(GuiFactory& fac)
{
return fac.forB(*this);
}
};
void notify(A* sender, const NotificationType notification)
{
// Use A interface...
// Get the concrete GuiFactory from somewhere, and use it
auto gui = sender->createGui(win32GuiFactory);
}
If you want know type to persist your hierarchy, conside to use boost::TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).
If you want know type to process different types in different manners, conside to use Visitor insted of type identifier or make abstract interface with virtual functions covers your needs.
EDITED
Your goal is to create different UI object for different types. You can use the following model to reach your goal:
class UIObject {...};
class UIObjectFactory {...};
class A {
public:
virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0;
};
void OnNotify(A* sender) {
auto ptr = sender->Create(GetUIFactory());
...
}
and defining virtual method:
virtual ClassType get_type(void) const;
The easiest way to achieve this and get rid of scalability issue is to implement your get_type() member function in each class A, B, C, ... this way:
typedef uintptr_t ClassType;
virtual ClassType get_type() const
{
static int dummy;
return reinterpret_cast<ClassType>(&dummy);
}
A static variable dummy will be created for each class you add this member function, so that the return value identifies uniquely the class.

How to implement nested fluent interface?

I have a task to implement fluent interface for a class, which consist of other classes. Let's say we have a class:
class Pizza {
int price, size;
}
class Foo {
string name;
Pizza p1, p2;
}
I would like to use code like:
Foo f = FooBuilder().setName("foo")
.settingP1().setPrice(5).setSize(1)
.settingP2().setPrice(2)
.build();
but I also would like to forbid code like:
Foo f = FooBuilder().setName("foo").setPrice(5);
I thought about a class inherited from FooBuilder which is returned after calling .settingP1() but I am not sure how to do it. Notice that I don't want to write .build() when I ended specifying Pizza object.
EDIT: Maybe I should've mentioned that when I wrote .settingP2().setPrice(2) without writing .setSize(sth) I meant that size will just have default value. I want to be able to "jump" to the next object regardless of specifying all attributes or not
EDIT2: I know how to implement the Builder pattern and fluent interface for classes which have fields of basic types. The problem is I want the code
Foo f = FooBuilder().setName("foo").setPrice(5);
to not compile. Maybe it's impossible to write such a builder.
If you don't mind, I'll write solution for your problem in Java, hopefully you'll be able to apply it in C++ without anyu problem.
You have 2 options.
More verbose DSL (I prefer not to call your problem Builder any more, but either Fluent API, or DSL - Domain Specific Language, as it defines grammar rules for it) with simpler implementation
or simpler DSL (exactly what you wrote) with a small trick in the implenmentation.
For optiona #1 your usage would look like this:
new FooBuilder().setName("Foo")
.settingP1().setPrice(5).setSize(1).end()
.settingP2().setPrice(2).end()
.build();
Notice additional methods end(). Corresponding code in Java would look like this:
public class FooBuilder {
public FooBuilder setName(String name) {
// Store the name
return this;
}
public PizzaBuilder settingP1() {
return new PizzaBuilder(pizza1, this);
}
public PizzaBuilder settingP2() {
return new PizzaBuilder(pizza2, this);
}
public Foo build() {
// return Foo build using stored information
}
}
public class PizzaBuilder {
private final Pizza pizza;
private final FooBuilder foo;
// Constructor
public PizzaBuilder(Pizza pizza, FooBuilder foo) {
this.pizza = pizza;
this.foo = foo;
}
public PizzaBuilder setPrice(int price) {
// update pizza price
return this;
}
public PizzaBuilder setSize(int size) {
// update pizza size
return this;
}
// With this method you return to parent, and you can set second pizza.
public FooBuilder end() {
return foo;
}
}
Now for option #2 I'd do another generalization to your problem to allow defining any number of pizzas. I'd also omit set prefix, it's not usual for DSL:
new FooBuilder().name("Foo")
.addPizzaWith().price(5).size(1)
.addPizzaWith().price(2)
.build();
Now the implementation will look like:
public class FooBuilder {
public FooBuilder(String name) {
// Store name
return this;
}
public PizzaBuilder addPizzaWith() {
Pizza pizza = createAndStorePizza(); // Some private method to do what is says
return new PizzaBuilder(pizza, this);
}
public Foo build() {
// Build and return the Foo using stored data
}
}
public class PizzaBuilder {
private final Pizza pizza;
private final FooBuilder foo;
public PizzaBuilder(Pizza pizza, FooBuilder foo) {
this.pizza = pizza;
this.foo = foo;
}
public PizzaBuilder price(int value) {
// Store price value
return this;
}
public PizzaBuilder size(int value) {
// Store size value
return this;
}
// This method does the trick - it terminates first pizza specification,
// and delegates entering second (or any other) pizza specification to
// the parent FooBuilder.
public PizzaBuilder addPizzaWith() {
return foo.addPizzaWith();
}
// Another similar trick with allowing to call build directly on Pizza
// specification
public Foo build() {
return foo.build();
}
}
There is one noticeable attribute - circular dependency. FooBuilder must know PizzaBuilder, and PizzaBuilder must know FooBuilder. In Java it's not an issue.
If I remember correctly, you can solve it in C++ too by declaring first just the
type using forward declaration or so.
It would also be typically beneficial for the second example in Java to introduce an interface with methods build() and addPizzaWith(), which both classes implement. So you can e.g. add pizzas in cycle without any issue.
Dmitri Nesteruk has written a "facet builder" example that is pretty much what you are trying to achieve.
The basic structure would be something like (almost pseudo code):
class FooBuilderBase {
protected:
Foo& foo; // reference to derived builders
FooBuilderBase(Foo& f) : foo(f) {}
public:
PizzaBuilder settingP1() { return PizzaBuilder(foo, foo.p1); }
PizzaBuilder settingP2() { return PizzaBuilder(foo, foo.p2); }
};
class FooBuilder : public FooBuilderBase {
Foo foo_; // real instance
public:
FooBuilder() : FooBuilderBase(foo_) {}
FooBuilder& setName(string n) { foo.name = n; return *this; }
};
class PizzaBuilder : public FooBuilderBase {
Pizza& pizza;
public:
PizzaBuilder(Foo& f, Pizza& p) : FooBuilderBase(f), pizza(p) {}
PizzaBuilder& setPrice(int p) { pizza.price = p; return *this; }
};
You can add a FooPizzaBuilder class as derrivate of FooBuilder.
By doing this you seperate the building of your Pizza classes and the building of the actual Foo class.
Consider the following code:
enum class PizzaNum {
ONE, TWO
}
class FooPizzaBuilder;
class FooBuilder {
public:
FooBuilder();
FooBuilder setName();
FooPizzaBuilder settingP1();
FooPizzaBuilder settingP2();
Foo build();
protected:
void _setPrize(PizzaNum); //Don't expose _setPrice() to user
void _setSize(PizzaNum); //Don't expose _setSize() to user
}
class FooPizzaBuilder : public FooBuilder {
public:
FooPizzaBuilder(PizzaNum pizzaNum)
FooPizzaBuilder setPrice(); //Call _setPrice()
FooPizzaBuilder setSize(); //Call _setSize()
}
This requires you to call settingP1() before making a call to setPrice();
An easy way to make the code type safe is to add an enum class to FooBuilder.
class FooBuilder {
public:
enum class PizzaNum {
ONE,
TWO
}
}
and...
FooBuilder& FooBuilder::setPrice(const PizzaNum pizzaNum, const int price) {
switch (pizzaNum) {
case PizzaNum::ONE:
p1.setPrice(price);
break;
case PizzaNum::TWO:
p2.setPrice(price);
break;
}
return this;
}
Then, you need to pass the enum to the method otherwise it results in a compile time error (e.g. .setPrice(FooBuilder::PizzaNum::ONE, 5).
Note, this is non-variadic.

C++ class type array

I am loading different types of derived classes from a file, which are of the form:
4-byte class ID header
n-byte serialized data
Each of the classes are inherited from a same base class, but I have some trouble creating them elegantly. This is my current code (here Foo and Bar are inherited from the same type):
// read class ID
uint32_t id = ReadHeader(myFile);
// create correct class
switch (id)
{
case ID_CLASS_FOO: myClass = new Foo(myFile); break;
case ID_CLASS_BAR: myClass = new Bar(myFile); break;
/* ... */
}
But I find this rather ugly, tedious and prone to error, since for every extra class I add, I need one extra define/enum member, and one additional line in the switch.
What I am looking for is something where I would declare a compile-time "type array" like such:
ClassTypes = {Foo, Bar, ...};
And then, when reading the file, just go:
myClass = new ClassTypes[id](myFile);
Is there some way to do this in C++?
You could create a factory class.
Factory definition:
typedef ClassType* (*ClassCreation(void))
class ClassFactory
{
private:
map<ClassId, ClassCreation> creators;
public:
ClassFactory()
{
creators[ID_CLASS_FOO] = &Foo::create;
creators[ID_CLASS_BAR] = &Bar::create;
}
ClassType* getClassType(ClassId id)
{
return (creators[id])()
}
};
class ClassType
{
//etc
};
class Foo : public ClassType
{
public:
static ClassType* create()
{
return new Foo;
}
};
class Bar : public ClassType
{
public:
static ClassType* create()
{
return new Bar;
}
};
Factory use:
ClassFactory factory;
uint32_t id = ReadHeader(myFile);
ClassType* myClass = factory.getClassType(id);
What about a static function in your base class that looks something like:
ClassTypes create(FileType myFile)
{
// read class ID
uint32_t id = ReadHeader(myFile);
// create correct class
switch (id)
{
case ID_CLASS_FOO: myClass = new Foo(myFile); break;
case ID_CLASS_BAR: myClass = new Bar(myFile); break;
/* ... */
}
return myClass;
}
At least that way, instead of
myClass = new ClassTypes[id](myFile);
you could do
myClass = ClassTypes::create(myFile);
Assuming your IDs go 0, 1, 2, 3, ..., What you could do is to create a std::map that maps each of the message ID to a function pointer to named constructor that creates the right kind of object for that ID.
class BaseClass {
private:
typedef (BaseClass*) (*NamedConstructor) (SomeType &);
// The map.
static std::map<int, NamedConstructor> id_to_constructor;
public:
// All the possible message types.
enum MessageType {
FooMsg = some_value,
BarMsg = some_other_value,
... // potentially a whole lot more
};
// Add a named constructor to the map.
static void add_handler (MessageType id, NamedConstructor cotr) {
// Error handling such as duplicates left as an exercise to the user.
id_to_constructor[id] = cotr;
}
// Function that applies the map.
static void handle_message (int id, SomeType & my_file) {
// Error handling such as a missing entry left as an exercise to the user.
NamedConstructor cotr = id_to_constructor[id];
cotr (my_file);
}
...
};
class Foo : public BaseClass {
public:
static BaseClass* create_foo (SomeType & my_file) {
return new Foo (my_file); // Or use a smart pointer.
}
// Member data and member functions elided.
...
};
class Bar : public BaseClass {
public:
static BaseClass* create_bar (SomeType & my_file) {
return new Bar (my_file); // Or use a smart pointer.
}
// Member data and member functions elided.
...
};
You'll need some mechanism to register the named constructors Foo::create_foo(), Bar::create_bar(), etc. using the BaseClass method add_handler. If you have 500 message types, that's 500 lines of code, but it will be straight line (no if, no switch) code.
The alternative is a switch statement with 500 cases. Yech.
So why a map rather than an vector? If you know the IDs will go 0, 1, 2, ..., a vector is fine. What if you have gaps? What if by design you have big huge gaps? For example, the message IDs might be Hamming-encoded so as to reduce errors.