Thread overview
Using templates to switch interface implementation class
May 21, 2006
Marcin Kuszczak
May 21, 2006
Tom S
May 22, 2006
Marcin Kuszczak
May 23, 2006
Tom S
May 21, 2006
Hello!

I tried to intelligently change implementation class. What do I mean by intelligently? Here are my requirements:

1. It should be possible to change every implementation separately not by
using some global switch.
2. It is not necessary to switch implementation classes on runtime.
3. Program should use configuration file (in d language) to store
information about which implementation classes should be used.
4. It seems that it would be good idea to bind interface name with concrete
implementation class in above mention configuration class.

Above requirements were fullfilled in C++ program which we write in our company. Such an architecture was necessary to abstract from concrete view classes (MFC) and use special test classes intstead. Solution is done using templates and some macro magic and is a little bit hackish, but anyway works just good.

In configuration file you just write sth. like this:
#include "mainviewtest.h"
BIND_INSTANCE(IMainView, MainViewTest);

and in code you use factory with templates to instantiate implementation class.

My question is how to achieve same effect in D?

---

I tried to prepare sth. what partially works, but is still not enough. Below you can find (working only for one binding) solution.

------------------------
main.d:
import instancefactory;
import imainview;

void main() {
        IMainView mv=(new ViewFactory!(IMainView)).getInstance();
        mv.forward();
        mv.showList();
}

------------------------
imainview.d:
module imainview;

interface IMainView {
        public void forward();
        public void showList();
        public void getData();
}



------------------------
instanceconfig.d:

module instanceconfig;

template Bind(I, T) {
        alias T PT;
        template getInstance(MI:I) {
                MI getInstance() {
                        return new PT;
                }
        }
}

import vcards.uiview.model.imainview;
import vcards.uiview.test.mainview_test;
import vcards.uiview.impl.mainview;
mixin Bind!(IMainView, MainViewTest);

-- 
Regards
Marcin Kuszczak
(Aarti_pl)
May 21, 2006
I'm attaching the best solution I could come up with...
The binding is done in a static module ctor. Creating an 'implementation
instance' for a given interface incurs a cost of a virtual function call
and there's a minimal storage penalty, but at least it's not very
hackish and its usage is very simple.


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O
!M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/


May 22, 2006
Tom S wrote:

> I'm attaching the best solution I could come up with...
> The binding is done in a static module ctor. Creating an 'implementation
> instance' for a given interface incurs a cost of a virtual function call
> and there's a minimal storage penalty, but at least it's not very
> hackish and its usage is very simple.
> 
> 

Thanks! It looks like this solution is working pretty good.


But if anyone have idea how to make it completely using static templates to achieve same effect it would be interesting for me. Especially I wonder why my code doesn't work as expected (It works for one binging, but not for more):

1.      template Bind(I, T) {
2.              alias T PT;
3.              template getInstance(MI:I) {
4.                      MI getInstance() {
5.                              return new PT;
6.                      }
7.              }
8.      }

1) Why there must be alias in line 2? without this "alias" in line 5
compiler can not see T from line 1.
2) Do I understand it correctly that above code should instantiate to e.g.:
        template getInstance(MI:IMainView) {
                MI getInstance() {
                return new MainViewTest;
                }
        }
as it is not possible to put anything instead of 'MI' when instantiating?

It would  be great if someone could explain me how does it work... :-)

PS. It's good to have helpful hand in D here in Poland. Kraków sends greetings to Toruń :-)

Regards
Marcin Kuszczak
(Aarti_pl)

May 23, 2006
Marcin Kuszczak wrote:
> But if anyone have idea how to make it completely using static templates to
> achieve same effect it would be interesting for me. Especially I wonder why
> my code doesn't work as expected (It works for one binging, but not for
> more):
> (...)

There are a few problems with templates and mixins. I've posted about them to digitalmars.D, we'll see if something can be done about them...


> 1) Why there must be alias in line 2? without this "alias" in line 5
> compiler can not see T from line 1.

Not sure, it might be a bug, but it may be related to one sentence from the spec: "Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined".


> 2) Do I understand it correctly that above code should instantiate to e.g.:
>         template getInstance(MI:IMainView) {
>                 MI getInstance() {
>                 return new MainViewTest;
>                 }
>         }
> as it is not possible to put anything instead of 'MI' when instantiating?

Sorry, but I don't understand what you're asking about...


> PS. It's good to have helpful hand in D here in Poland. Kraków sends
> greetings to Toruń :-)

I'm always there to help fellow D coders ;) Greetings from Torun !


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/