我有两个班,Foo<T>和Bar,这是互相依赖的,以及各种其他类.我使用Dagger-2进行依赖注入,但如果我天真地添加循环依赖,Dagger会在运行时遇到堆栈溢出.什么是重构类来解决这个问题的好方法,同时仍然使用Dagger注入所有其他依赖项,并且对现有调用的重复和更改最少?
当我将@nest/swagger库更新到版本 4 时,发生了此错误:
(node:16134) UnhandledPromiseRejectionWarning: Error: A circular dependency has been detected (property key: "customer"). Please, make sure that each side of a bidirectional relationships are using lazy resolvers ("type: () => ClassType").
at SchemaObjectFactory.createNotBuiltInTypeReference (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:182:19)
at SchemaObjectFactory.mergePropertyWithMetadata (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:117:25)
at /opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:66:35
at Array.map (<anonymous>)
at SchemaObjectFactory.exploreModelSchema (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:65:52)
at SchemaObjectFactory.createNotBuiltInTypeReference (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:187:37)
at SchemaObjectFactory.mergePropertyWithMetadata (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:117:25)
at /opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:66:35
at Array.map (<anonymous>)
at SchemaObjectFactory.exploreModelSchema (/opt/desenvolvimento/Haizen/projectx_back/node_modules/@nestjs/swagger/dist/services/schema-object-factory.js:65:52)
Run Code Online (Sandbox Code Playgroud)
我的模型类似乎是这样的:
@Entity()
export class Job {
.
.
.
@ManyToOne(type => Customer, customer => customer.jobs)
@ApiProperty({ type: …Run Code Online (Sandbox Code Playgroud) 假设我们有两个类,Foo和Foo Sub,每个类分别位于不同的文件foo.rb和foo_sub.rb中.
foo.rb:
require "foo_sub"
class Foo
def foo
FooSub.SOME_CONSTANT
end
end
Run Code Online (Sandbox Code Playgroud)
foo_sub.rb:
require "foo"
class FooSub < Foo
SOME_CONSTANT = 1
end
Run Code Online (Sandbox Code Playgroud)
由于循环依赖,这不起作用 - 我们无法定义任何一个没有另一个的类.我见过各种各样的解决方案.其中两个我想避免 - 即将它们放在同一个文件中并删除循环依赖.所以,我发现的唯一其他解决方案是前向声明:
foo.rb:
class Foo
end
require "foo_sub"
class Foo
def foo
FooSub.SOME_CONSTANT
end
end
Run Code Online (Sandbox Code Playgroud)
foo_sub.rb
require "foo"
class FooSub < Foo
SOME_CONSTANT = 1
end
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我有三个文件,我就无法做同样的事情:
foo.rb:
class Foo
end
require "foo_sub_sub"
class Foo
def foo
FooSubSub.SOME_CONSTANT
end
end
Run Code Online (Sandbox Code Playgroud)
foo_sub.rb:
require "foo"
class FooSub < Foo
end
Run Code Online (Sandbox Code Playgroud)
foo_sub_sub.rb:
require "foo_sub"
class FooSubSub < …Run Code Online (Sandbox Code Playgroud) 我只是在阅读 R. Martin和M. Martin的C#中的敏捷原则,模式和实践,并在他们的书中建议将所有接口保存在一个单独的项目中,例如.接口.
举个例子,如果我有一个包含所有自定义Gui类的Gui项目,我会将它们的接口保留在Interfaces项目中.具体来说,我在Gui中有一个CustomButton类,我会在Interfaces中保留ICustomButton 接口.
优点是,任何需要ICustomButton的类都不需要引用Gui本身,而只需要更轻量级的Interfaces项目.
此外,如果Gui项目中的一个类发生更改并因此导致它被重建,则只有直接引用CustomButton的项目才需要重新编译,而引用ICustomButton的项目可能保持不变.
我理解这个概念,但看到一个问题:
可以说我有这个界面:
public interface ICustomButton
{
void Animate(AnimatorStrategy strategy);
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它指的是AnimatorStrategy,它是一个具体的类,因此会坐在不同的项目中,我们称之为动画.现在接口项目需要引用动画.另一方面,如果Animation使用Interfaces中定义的接口,则需要引用它.
循环依赖 - "我们来了".
我看到,这个问题的唯一解决方案是,接口中定义的所有方法都接受本身作为接口的输入.试图实现这一点,很可能会产生多米诺骨牌效应,并且很快就需要为最基本的类实现接口.
我不知道我是否愿意在开发中处理这种开销.
有什么建议?
我在各种网站上看过几篇文章,提出通过使用依赖注入解决.NET程序集之间的循环依赖关系.这可能会解决构建错误,但它并没有真正解决循环依赖,是吗?对我来说,架构中似乎仍然存在逻辑错误.我是疯了还是其他人都同意1)这是一个不太好的DI使用,2)不是解决循环依赖问题的适当方法?
我有两节课,foo和bar.
foo.h #includes bar.h并包含一个std::vector指向bar对象的指针.在运行时期间的某个时刻,bar必须访问指向其他bar对象的指针向量.因此,foo包含一个getBarObjects()返回指针数组的方法.
因此,我foo在bar.h中转发声明.我显然还要转发声明我正在使用的方法 - foo::getBarObjects().当这返回指针数组时bar,我陷入了恶性循环.
我无法转发声明Bar然后只是转发声明getBarObjects(),因为这导致"不允许不完整的类型名称".
foo.h中:
#include "bar.h"
#include <vector>
class foo {
public:
foo();
~foo();
std::vector<bar*> getBarObjects();
private:
std::vector<bar*> barObjects;
}
Run Code Online (Sandbox Code Playgroud)
bar.h:
class foo;
std::vector<bar*> foo::getBarObjects(); // error, doesn't know bar at this point
class bar {
public:
bar(foo *currentFoo);
~bar();
bool dosth();
private:
foo *thisFoo;
}
Run Code Online (Sandbox Code Playgroud)
bar.cpp:
#include "bar.h"
bool bar(foo …Run Code Online (Sandbox Code Playgroud) 我在不同的情况下遇到过几次这个问题,但我的设置如下:
我有两个Django模型文件.一个包含用户可以用来注册课程的用户模型和CouponCodes.这些都在account/models.py文件中.课程和相关的多对多字段位于不同的模型文件course/models.py中.我通常在我的代码中将这些分别称为amod和cmod.
在课程/ models.py中我有一个import语句:
from account import models as amod
class Course(ExtendedModel):
stuff = stuff
Run Code Online (Sandbox Code Playgroud)
我需要为Course和User之间的多对多模型/表导入account/models.py文件,这里没有显示.到现在为止还挺好.
在account/models.py文件中,我有CouponCode模型.每个实例都会创建,然后可以在创建后分配给特定的Course对象,以允许学生使用它来注册系统中的课程.
class CouponCode(ExtendedModel):
assigned_course = UniqueIDForeignKey("course.Course", blank=True, null=True, related_name='assigned_coupon_code_set')
...
...
@staticmethod
def assign_batch(c, upper_limit):
import course.models as cmod # Why is this allowed here?
assert isinstance(c, cmod.Course)
# Do other stuff here
Run Code Online (Sandbox Code Playgroud)
这种静态方法允许我传入一个课程对象和一些我想要分配给它的CouponCodes,然后它将为该课程分配下N个未分配的代码.我的问题来自断言.
我需要从course/models.py导入Course对象,以确保传入的对象实际上是Course的一个实例,但是如果我在文件顶部执行此操作,则会出现问题,因为此文件已经存在被导入到course/models.py中.(amod正被导入到cmod中,然后在amod中我需要导入cmod).
为什么它允许我这样做,如果我在我需要它之前在方法中导入它而不是在文件的顶部?
我很惊讶地发现,在Babel中,我可以import互相拥有两个模块而没有任何问题.我发现有一些地方将此称为Babel中已知和预期的行为.我知道这被广泛认为是很多(我猜的是最多)人的反模式,但请忽略这个问题:
有谁知道这是否(或将是)在ES6/7中的正确行为?
我能找到官方答案(和技术解释)最接近的是2ality.com上的评论
javascript circular-dependency ecmascript-6 babeljs ecmascript-7
我有两个函数之间的循环依赖.我希望这些函数中的每一个都驻留在它自己的dll中.是否可以使用visual studio构建它?
foo(int i)
{
if (i > 0)
bar(i -i);
}
Run Code Online (Sandbox Code Playgroud)
- >应该编译成foo.dll
bar(int i)
{
if (i > 0)
foo(i - i);
}
Run Code Online (Sandbox Code Playgroud)
- >应该编译成bar.dll
我在visual studio中创建了两个项目,一个用于foo,一个用于bar.通过玩'参考'并编译几次,我设法获得了我想要的dll.我想知道视觉工作室是否提供了一种以干净的方式做到这一点的方法.
如果foo改变了,bar不需要重新编译,因为我只依赖于bar的签名,而不是bar的实现.如果两个dll都有lib存在,我可以将新功能重新编译为两者中的任何一个,整个系统仍然有效.
我尝试这个的原因是我有一个循环依赖的遗留系统,目前静态链接.出于各种原因,我们想要转向dll.我们不想等到清理所有循环依赖项.我正在考虑解决方案,并在linux上用gcc尝试了一些东西,在那里可以做我建议的.因此,您可以拥有两个彼此依赖的共享库,并且可以彼此独立构建.
我知道循环依赖并不是一件好事,但这不是我想要的讨论.
我在Golang有一个包含几个模块的项目.由于以下场景,我遇到循环导入问题:
模块游戏包含具有当前游戏状态的结构.另一个模块(Modifier)正在做一些游戏特定的东西和计算,因此修改了游戏状态.因此,Modifier将需要struct Game,但不需要来自Game的任何方法.从Game中调用修饰符,这里我们有循环导入.
游戏启动修改器
修饰符需要Game结构
在我看来,这是一个常见的场景,所以我想知道我应该如何以最好的方式解决它.我的解决方案是创建第三个模块"Structs",它只包含整个应用程序的所有结构.这是一个好的解决方案吗?
c++ ×2
.net ×1
architecture ×1
babeljs ×1
c# ×1
dagger ×1
dagger-2 ×1
django ×1
dll ×1
ecmascript-6 ×1
ecmascript-7 ×1
go ×1
import ×1
interface ×1
javascript ×1
nestjs ×1
python ×1
require ×1
ruby ×1
swagger ×1