Thread overview
How to store a pointer to class contructor
Dec 24, 2020
Dmitriy Asondo
Dec 24, 2020
Dmitriy Asondo
Dec 24, 2020
Mike Parker
Dec 24, 2020
Dmitriy Asondo
Dec 24, 2020
Mike Parker
Dec 24, 2020
Jacob Shtokolov
Dec 25, 2020
Jacob Carlborg
December 24, 2020
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 :)
December 24, 2020
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


December 24, 2020
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;
}
```

December 24, 2020
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

December 24, 2020
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;
December 24, 2020
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?
December 25, 2020
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