www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using templates to switch interface implementation class

reply Marcin Kuszczak <aarti interia.pl> writes:
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
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

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 21 2006
parent reply Marcin Kuszczak <aarti interia.pl> writes:
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 22 2006
parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
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 +/
May 23 2006