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
- 使用适当的内容初始化内存(
-这会保存诸如a=50、指向虚拟表的指针等的值。)typeid().init
- 调用构造函数
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
- 使用适当的内容初始化内存(
-这会保存诸如a=50、指向虚拟表的指针等的值。)typeid().init
- 调用构造函数
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可以将其分配给成员变量)