www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to store a pointer to class contructor

reply Dmitriy Asondo <dmitriy.asondo gmail.com> writes:
Hi!

You may hate me, but currently I'm using nodejs. I want to use 
dlang as a second instrument and I'm trying to check some js-like 
features. For example, if I want to store somewhere in 
array|tuple a list of pointers to classes (app services) how may 
I do that?

I expect code like this:
----------------------
class OloloService {}
class BlablaService {}

auto servicesList = [OloloService, BlablaService];
auto serviceInstance = new servicesList[1](args);
----------------------


But such costructions is impossible in D, so, may be anybody may 
explain how to organize app "services" and what ways of 
dependency injection exist for D?

Thank you :)
Dec 24 2020
next sibling parent reply Dmitriy Asondo <dmitriy.asondo gmail.com> writes:
The idea is to store somewhere services (classes) first and only 
when the app need - instantiate services for 
app/thread/http-request (as option) and provide values to 
constructors via DI
Dec 24 2020
parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 24 December 2020 at 10:33:00 UTC, Dmitriy Asondo 
wrote:
 The idea is to store somewhere services (classes) first and 
 only when the app need - instantiate services for 
 app/thread/http-request (as option) and provide values to 
 constructors via DI
There's `Object.factory`, which constructs a class instance from a fully-qualified name: https://dlang.org/phobos/object.html#.Object.factory But IIRC there are issues with it in some cases and I believe it's supposed to be deprecated at some point. I'd just give the classes an interface and use function pointers to construct them: ``` interface IService { ... } alias ServiceMaker = IService function(); ServiceMaker[string] serviceRegistry; class FooService : IService { ... } IService makeFooService() { return new FooService(); } void registerServices() { serviceRegistry["FooService"] = &makeFooService; } ```
Dec 24 2020
parent reply Dmitriy Asondo <dmitriy.asondo gmail.com> writes:
On Thursday, 24 December 2020 at 11:02:11 UTC, Mike Parker wrote:
 On Thursday, 24 December 2020 at 10:33:00 UTC, Dmitriy Asondo 
 wrote:
 The idea is to store somewhere services (classes) first and 
 only when the app need - instantiate services for 
 app/thread/http-request (as option) and provide values to 
 constructors via DI
There's `Object.factory`, which constructs a class instance from a fully-qualified name: https://dlang.org/phobos/object.html#.Object.factory But IIRC there are issues with it in some cases and I believe it's supposed to be deprecated at some point. I'd just give the classes an interface and use function pointers to construct them: ``` interface IService { ... } alias ServiceMaker = IService function(); ServiceMaker[string] serviceRegistry; class FooService : IService { ... } IService makeFooService() { return new FooService(); } void registerServices() { serviceRegistry["FooService"] = &makeFooService; } ```
Hm... So, I need helpers like common interface for services & function-factory for every. It would be difficult to automate) Ok, I see, thank you! Is there any way, for example on compile step, to get class name from class pointer? To automate generation of factory via template
Dec 24 2020
parent Mike Parker <aldacron gmail.com> writes:
On Thursday, 24 December 2020 at 11:15:28 UTC, Dmitriy Asondo 
wrote:

 Is there any way, for example on compile step, to get class 
 name from class pointer? To automate generation of factory via 
 template
At compile time, you'd get it from the type, not the reference: typeid(T).name;
Dec 24 2020
prev sibling next sibling parent Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Thursday, 24 December 2020 at 10:23:09 UTC, Dmitriy Asondo 
wrote:
 Hi!

 I'm trying to check some js-like features. For example, if I 
 want to store somewhere in array|tuple a list of pointers to 
 classes (app services) how may I do that?
Hi, it seems that what you're looking for is Prototype Inheritance, which is not quite common among staticly typed programming languages due to its runtime nature. Please note that the way you've implemented it in JavaScript doesn't take compile-time class constructors into consideration. Just look at how you're passing constructor parameters to your objects. In D, each class may have its own constructor, so the arguments may be totally different. Also, it looks like you're trying to implement some kind of a Service Locator. Could you tell what are you trying to achieve with this code? Are the arguments and the array index received at runtime?
Dec 24 2020
prev sibling parent Jacob Carlborg <doob me.com> writes:
On Thursday, 24 December 2020 at 10:23:09 UTC, Dmitriy Asondo 
wrote:

 I expect code like this:
 ----------------------
 class OloloService {}
 class BlablaService {}

 auto servicesList = [OloloService, BlablaService];
 auto serviceInstance = new servicesList[1](args);
 ----------------------
Here's a slightly different version that I think is closer to your original example: import std; interface Service {} mixin template Constructor() { this(int a) { } } class OloloService : Service { mixin Constructor; } class BlablaService : Service { mixin Constructor; } Service function(int) create(T)() { return a => new T(a); } void main() { auto servicesList = [create!OloloService, create!BlablaService]; auto serviceInstance = servicesList[1](3); writeln(serviceInstance); } Since D is a statically typed language you need a form of base type if you want to store a list of values of different types. In this case, the base type is `Service`. If you want to have a constructor, as you do in your original example, the constructor needs to have the same signature for all types, the mixin template helps with that. You can use a tuple as well to store different values of different types. But then everything need to be known at compile time. That is, the index, in your case. -- /Jacob Carlborg
Dec 25 2020