如何处理循环引用?

时间:2022-08-23 08:32:33

If I have those two projects:

如果我有两个项目:

MyCompany.ERP.Billing
MyCompany.ERP.Financial

Billing asks/sends information to Financial and vice-versa. Both are too big so I don't want to put them in a single project. Visual Studio doesn't allow circular references. How would you deal with that?

计费询问/发送信息到财务部门,反之亦然。两者都太大了,所以我不想把它们放在一个项目中。Visual Studio不允许循环引用。你会怎么处理呢?

4 个解决方案

#1


24  

Extract interfaces from your classes and put them into a core project referenced from both Billing and Financial projects. You can then use those interfaces to share data between assemblies.

从类中提取接口,并将它们放入从帐单和财务项目中引用的核心项目中。然后可以使用这些接口在程序集之间共享数据。

This only allows you to pass objects between those 2 assemblies, but you can't create objects from the other since you don't actually have a reference to begin with. If you want to be able to create objects you need a factory, external to those 2 projects, that handles object creation.

这只允许您在这两个程序集之间传递对象,但是您不能从另一个程序集中创建对象,因为您实际上没有开始的引用。如果你想要创建对象,你需要一个工厂,在这两个项目之外,用来处理对象创建。

I would extract the business logic that needs to share the data back and forth between Billing and Financial into another project. This would make things a lot easier and would save you from resorting to all sort of tricks that make maintainability a nightmare.

我将提取业务逻辑,以便在账单和财务之间来回共享数据。这将使事情变得更加容易,并且可以避免使用各种使维护性成为恶梦的技巧。

#2


5  

Having too large of a project shouldn't be an issue. You can keep your code structured with namespaces and different folders for the source code. In this case circular references are no longer an issue.

项目规模过大不应该是问题。您可以使用源代码的名称空间和不同文件夹来保持代码的结构化。在这种情况下,循环引用不再是问题。

#3


3  

The answer mentioning interfaces is correct - but if you need to be able to create both types from both projects, you'll either need to farm a factory out into yet another project (which would also reference the interfaces project but could be referenced by both of your main projects) or change the structure you're using significantly.

答案提到接口是正确的,但如果您需要能够创建两种类型的项目,你要么需要农场一个工厂到另一个项目(这也会引用接口项目但可以引用的主要项目)或改变你使用显著的结构。

Something like this should work:

像这样的东西应该是有用的:

Finance: References Billing, Interfaces, Factory
Billing: References Finance, Interfaces, Factory
Factory: References Interfaces

Factory would have a BillingFactory.CreateInstance() As Interfaces.IBilling and also the abstract Billing class which implement Interfaces.IBilling.

工厂将有一个BillingFactory.CreateInstance()作为接口。IBilling以及实现Interfaces.IBilling的抽象billclass。

The only issue I can see is if you need to do something clever when instantiating an object and don't want that logic to end up in a separate project - but as you haven't mentioned any clever logic to instantiate, this should be sufficient

我能看到的唯一问题是,如果在实例化一个对象时需要做一些聪明的事情,并且不希望该逻辑最终出现在一个单独的项目中——但是由于您没有提到要实例化的任何聪明逻辑,这应该足够了

#4


0  

This solution could end up as a workaround for the circular reference problem. Basically you use #if logic around the code that doesn't compile unless the reference exists, and you use conditional compilation in the project file to define a variable only if the needed assembly exists. As a result, on first download from source, or after a solution clean, you must compile twice. Subsequent builds/rebuilds only require 1 build as normal. The nice thing about this is you never have to manually comment/uncomment #define statements.

这个解决方案可以作为循环引用问题的解决方案。基本上,在代码周围使用#if逻辑,除非引用存在,否则不会编译;在项目文件中使用条件编译,只在需要的程序集存在时定义变量。因此,在第一次从源代码下载或解决方案清理之后,您必须编译两次。后续的构建/重建只需要一个正常的构建。这样做的好处是,您不必手动地注释/取消注释#define语句。

#1


24  

Extract interfaces from your classes and put them into a core project referenced from both Billing and Financial projects. You can then use those interfaces to share data between assemblies.

从类中提取接口,并将它们放入从帐单和财务项目中引用的核心项目中。然后可以使用这些接口在程序集之间共享数据。

This only allows you to pass objects between those 2 assemblies, but you can't create objects from the other since you don't actually have a reference to begin with. If you want to be able to create objects you need a factory, external to those 2 projects, that handles object creation.

这只允许您在这两个程序集之间传递对象,但是您不能从另一个程序集中创建对象,因为您实际上没有开始的引用。如果你想要创建对象,你需要一个工厂,在这两个项目之外,用来处理对象创建。

I would extract the business logic that needs to share the data back and forth between Billing and Financial into another project. This would make things a lot easier and would save you from resorting to all sort of tricks that make maintainability a nightmare.

我将提取业务逻辑,以便在账单和财务之间来回共享数据。这将使事情变得更加容易,并且可以避免使用各种使维护性成为恶梦的技巧。

#2


5  

Having too large of a project shouldn't be an issue. You can keep your code structured with namespaces and different folders for the source code. In this case circular references are no longer an issue.

项目规模过大不应该是问题。您可以使用源代码的名称空间和不同文件夹来保持代码的结构化。在这种情况下,循环引用不再是问题。

#3


3  

The answer mentioning interfaces is correct - but if you need to be able to create both types from both projects, you'll either need to farm a factory out into yet another project (which would also reference the interfaces project but could be referenced by both of your main projects) or change the structure you're using significantly.

答案提到接口是正确的,但如果您需要能够创建两种类型的项目,你要么需要农场一个工厂到另一个项目(这也会引用接口项目但可以引用的主要项目)或改变你使用显著的结构。

Something like this should work:

像这样的东西应该是有用的:

Finance: References Billing, Interfaces, Factory
Billing: References Finance, Interfaces, Factory
Factory: References Interfaces

Factory would have a BillingFactory.CreateInstance() As Interfaces.IBilling and also the abstract Billing class which implement Interfaces.IBilling.

工厂将有一个BillingFactory.CreateInstance()作为接口。IBilling以及实现Interfaces.IBilling的抽象billclass。

The only issue I can see is if you need to do something clever when instantiating an object and don't want that logic to end up in a separate project - but as you haven't mentioned any clever logic to instantiate, this should be sufficient

我能看到的唯一问题是,如果在实例化一个对象时需要做一些聪明的事情,并且不希望该逻辑最终出现在一个单独的项目中——但是由于您没有提到要实例化的任何聪明逻辑,这应该足够了

#4


0  

This solution could end up as a workaround for the circular reference problem. Basically you use #if logic around the code that doesn't compile unless the reference exists, and you use conditional compilation in the project file to define a variable only if the needed assembly exists. As a result, on first download from source, or after a solution clean, you must compile twice. Subsequent builds/rebuilds only require 1 build as normal. The nice thing about this is you never have to manually comment/uncomment #define statements.

这个解决方案可以作为循环引用问题的解决方案。基本上,在代码周围使用#if逻辑,除非引用存在,否则不会编译;在项目文件中使用条件编译,只在需要的程序集存在时定义变量。因此,在第一次从源代码下载或解决方案清理之后,您必须编译两次。后续的构建/重建只需要一个正常的构建。这样做的好处是,您不必手动地注释/取消注释#define语句。