Dependency injection 在不调用构造函数的情况下创建实例

Dependency injection 在不调用构造函数的情况下创建实例,dependency-injection,d,Dependency Injection,D,我想创建一个实例,注入几个字段,然后在该实例上调用构造函数 例如: class Foo { int a = 50; int b; this() { assert(a == 50 && b == 10); } } ... Foo bar = ???; bar.b = 10; bar.this(); 通常,Foo可能有多个重载构造函数。 在不干扰垃圾收集器和其他语言机制的情况下,最好的方法是什么 编辑:到目前为止,我得到的大多

我想创建一个实例,注入几个字段,然后在该实例上调用构造函数

例如:

class Foo {
    int a = 50;
    int b;

    this() {
        assert(a == 50 && b == 10);
    }
}

...

Foo bar = ???;
bar.b = 10;
bar.this();
通常,
Foo
可能有多个重载构造函数。 在不干扰垃圾收集器和其他语言机制的情况下,最好的方法是什么


编辑:到目前为止,我得到的大多数回答都是“你他妈的为什么要这么做?!”

我目前正在使用这种@Annotation驱动的系统来完成两件事:自动配置加载和自动依赖项注入。到目前为止,这两种方法都为我带来了巨大的生产力提升,而且它们在责任脱钩方面也创造了奇迹。(另见:)


虽然在D语言中可能不常见,但类似的方法在Java等其他语言中广泛使用。

我认为您应该更改构造函数以接受这些参数

但如果您真的愿意,可以将“bar=new Foo();”分解为三个步骤:

  • 分配具有适当大小的内存(
    \u特征(classInstanceSize
  • 使用适当的内容初始化内存(
    typeid().init
    -这会保存诸如a=50、指向虚拟表的指针等的值。)
  • 调用构造函数
当然,还要返回新的引用

import core.memory; // for GC.malloc
enum size = __traits(classInstanceSize, Foo); // get the size
auto memory = GC.malloc(size)[0 .. size]; // alloc mem and slice it for bounds checking
memory[] = typeid(Foo).init[]; // initialize the memory

Foo foo = cast(Foo) memory.ptr; // we can now cast it to the reference

foo.b = 10; // here's your special line

foo.__ctor(); // and now call the constructor. Can pass any arguments here, D will handle the overloads normally

assert(foo.a == 50); // ensure everything worked
assert(foo.b == 10);
assert(typeid(foo) == typeid(Foo));

// BTW don't use the variable memory anymore - only use the typed Foo instance
分解这些步骤还可以根据需要替换分配方法。Phobos的
std.conv.emplace
函数在单个函数中执行步骤2和步骤3,以使自定义分配更容易


但是,既然您想在步骤2和步骤3之间插入代码,就必须自己完成。

我认为您应该更改构造函数以接受这些参数

但如果您真的愿意,可以将“bar=new Foo();”分解为三个步骤:

  • 分配具有适当大小的内存(
    \u特征(classInstanceSize
  • 使用适当的内容初始化内存(
    typeid().init
    -这会保存诸如a=50、指向虚拟表的指针等的值。)
  • 调用构造函数
当然,还要返回新的引用

import core.memory; // for GC.malloc
enum size = __traits(classInstanceSize, Foo); // get the size
auto memory = GC.malloc(size)[0 .. size]; // alloc mem and slice it for bounds checking
memory[] = typeid(Foo).init[]; // initialize the memory

Foo foo = cast(Foo) memory.ptr; // we can now cast it to the reference

foo.b = 10; // here's your special line

foo.__ctor(); // and now call the constructor. Can pass any arguments here, D will handle the overloads normally

assert(foo.a == 50); // ensure everything worked
assert(foo.b == 10);
assert(typeid(foo) == typeid(Foo));

// BTW don't use the variable memory anymore - only use the typed Foo instance
分解这些步骤还可以根据需要替换分配方法。Phobos的
std.conv.emplace
函数在单个函数中执行步骤2和步骤3,以使自定义分配更容易


但是既然你想在第2步和第3步之间插入代码,你就得自己去做。

是的,我几乎决定不这样做。当然,通过构造函数传递所有内容都是可能的,但是如果你想连接5个以上的实例字段,那就太麻烦了(尽管你可能会争辩说一个类不应该有那么多依赖关系);我将继续使用一个显式初始化方法,在注入完成后调用该方法。这可能有助于创建成员的结构,然后将该结构传递给ctor(ctor可以将其分配给成员变量)是的,我已经决定不这样做了。当然,通过构造函数传递所有内容是可能的,但是如果你想连接5+个实例字段(尽管你可能会认为一个类不应该有那么多依赖项),这会变得非常麻烦;我将继续使用在注入完成后调用的显式初始化方法。这可能有助于生成成员的结构,然后将结构传递给ctor(ctor可以将其分配给成员变量)