In Visual Studio. NET, a solution can contain multiple projects, and a project can reference several other projects. During compilation, vs automatically determines the compilation sequence of each project. How exactly does vs calculate this order?
If you have learned the data structure, you can easily answer this question: topological sort ).
What is topological sorting? Let's take a look. The introduction on Baidu encyclopedia is as follows:
To sort the topology of a directed acyclic graph (DAG) g, all vertices in G are arranged in a linear sequence so that any pair of vertices u and v in the graph, if <u, v> ε E (G), then u appears before V in linear sequence.
The above description is abstract. It is better to explain it using actual cases. If you create an MVC solution xmedia in Vs, the projects included in the solution and the reference relationships between projects are shown in the following table:
Project |
Reference |
Xmedia |
Xmedia. controllers, xmedia. Models, xmedia. logics, xmedia. commons |
Xmedia. Controllers |
Xmedia. Models, xmedia. logics, xmedia. commons |
Xmedia. Models |
|
Xmedia. Logics |
Xmedia. Models, xmedia. commons |
Xmedia. commons |
|
The reference relationship between projects is a dependency. If project a references Project B, project a depends on Project B. Therefore, Project B must be compiled before project.
Based on experience, we can conclude that the compilation sequence of the above projects is xmedia. commons, xmedia. Models, xmedia. logics, xmedia. controllers, and xmedia. Of course, you can also check the first two items.
The project and reference relationships constitute a directed graph. The project is equivalent to vertex in the directed graph, the reference relationship is equivalent to edge in the directed graph, and the project compilation sequence is a topological sequence, theAlgorithmIt is called a topological sorting algorithm.
The following is a directed graph of the project reference relationship:
Brief description of the topological sorting algorithm:
(1) Select a vertex with an outbound degree of 0 from the directed graph and output it.
(2) Delete the vertex and delete all edges of the vertex.
(3) Repeat the preceding two steps until there is no vertex with a degree of 0 in the remaining graph.
According to the above algorithm, the running process is demonstrated as follows:
Step 1 select the xmedia. commons Node
Step 2 select the xmedia. Models Node
Step 3 select the xmedia. logics Node
Step 4 select the xmedia. controllers Node
Step 5 select an xmedia Node
Next we use C # To implementCodeImplement this algorithm.
Because topological sorting is a widely used algorithm, we will implement a general sorting algorithm. In this general algorithm, we take the relationship between vertices as dependencies. The Code is as follows:
Using System; Using System. Collections. Generic; Using System. LINQ; Namespace Leleapplication1 { /// <Summary> /// Topology Sorting class. /// </Summary> Public Class Topologicsort { /// <Summary> /// Topological order. /// </Summary> /// <Typeparam name = "tkey"> The key-Value Type of the node. </Typeparam> /// <Param name = "nodes"> A group of nodes. </Param> /// <Returns> Topological sequence. </Returns> /// <Exception CREF = "invalidoperationexception"> This exception is thrown if bidirectional or cyclic references exist. </Exception> Public Ienumerable < String > Orderby (ienumerable <topologicnode>Nodes ){ If (Nodes = Null ) Yield Break ; // Copy one copy for easy operation List <topologicnode> List = New List <topologicnode> (); Foreach ( VaR Item In Nodes) {topologicnode = New Topologicnode () {key = Item. Key }; If (Item. dependences! = Null ) Node. dependences = New List < String > (Item. dependences); list. Add (node );} While (List. Count> 0 ){ // Search for nodes with null Dependencies VaR Item = List. firstordefault (C => C. dependences = Null | C. dependences. Count = 0 ); If (Item! = Null ){ Yield Return Item. Key; // Remove used nodes and their Dependencies List. Remove (item ); Foreach ( VaR Othernode In List ){ If (Othernode. dependences! = Null ) Othernode. dependences. Remove (item. Key );}} Else If (List. Count> 0 ){ // If an undirected ring is found, an exception is thrown. Throw New Invalidoperationexception ( " There is a bidirectional reference or circular reference. " );}}}} /// <Summary> /// Topology node class. /// </Summary> Public Class Topologicnode { /// <Summary> /// Obtains or sets the key value of a node. /// </Summary> Public String Key { Get ; Set ;} /// <Summary> /// Obtains or sets the list of key values of the dependent nodes. /// </Summary> Public List < String > Dependences { Get ; Set ;}}}
The test code is as follows:
Using System; Using System. Collections. Generic; Namespace Leleapplication1 { Class Program { Static Void Main ( String [] ARGs) {list <Topologicnode> nodes = New List <topologicnode> (){ New Topologicnode () {key = " Xmedia " , Dependences = New List < String > (){ " Xmedia. Controllers " , " Xmedia. Models " , " Xmedia. Logics " , " Xmedia. commons " }}, New Topologicnode () {key = " Xmedia. Controllers " , Dependences = New List < String > (){ " Xmedia. Models " , " Xmedia. Logics " , " Xmedia. commons " }}, New Topologicnode () {key = " Xmedia. Logics " , Dependences = New List < String > (){ " Xmedia. Models " ," Xmedia. commons " }}, New Topologicnode () {key = " Xmedia. Models " }, New Topologicnode () {key = " Xmedia. commons " }}; // Output result of topological sorting Topologicsort sort = New Topologicsort (); Foreach ( VaR Key In Sort. orderby (nodes) {console. writeline (key) ;}console. Readline ();}}}
Shows the running result: