In the .NET BCL there are circular references between:
System.dll
and System.Xml.dll
System.dll
and System.Configuration.dll
System.Xml.dll
and System.Configuration.dll
Here's a screenshot from .NET Reflector that shows what I mean:
How Microsoft created these assemblies is a mystery to me. Is a special compilation process required to allow this? I imagine something interesting is going on here.
In software engineering, a circular dependency is a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.
To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.
A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.
A circular dependency was detected for the service of type 'UserService'. UserService -> PhoneService -> UserService. It even directly points out the exact services which depend on each other. Note that in some cases, the circle could be much larger.
I can only tell how the Mono Project does this. The theorem is quite simple, though it gives a code mess.
They first compile System.Configuration.dll, without the part needing the reference to System.Xml.dll. After this, they compile System.Xml.dll the normal way. Now comes the magic. They recompile System.configuration.dll, with the part needing the reference to System.Xml.dll. Now there's a successful compilation with the circular reference.
In short:
RBarryYoung and Dykam are onto something. Microsoft uses internal tool which uses ILDASM to disassemble assemblies, strip all internal/private stuff and method bodies and recompile IL again (using ILASM) into what is called 'dehydrated assembly' or metadata assembly. This is done every time public interface of assembly is changed.
During the build, metadata assemblies are used instead of real ones. That way cycle is broken.
It can be done the way Dykam described but Visual Studio blocks you from doing it.
You'll have to use the command-line compiler csc.exe directly.
csc /target:library ClassA.cs
csc /target:library ClassB.cs /reference:ClassA.dll
csc /target:library ClassA.cs ClassC.cs /reference:ClassB.dll
//ClassA.cs
namespace CircularA {
public class ClassA {
}
}
//ClassB.cs
using CircularA;
namespace CircularB {
public class ClassB : ClassA {
}
}
//ClassC.cs
namespace CircularA {
class ClassC : ClassB {
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With