mercredi 14 juillet 2021

Populate adjacency list of C# types and properties, with nodes into a Lookup

My problem is similar to this one, but I have something like two hundred classes that are all auto-generated from XML schemas[1] using XmlSchemaClassGenerator, and the top answer suggests marking each class with a custom attribute. This would take forever, so I would like to do it rather more heuristically with a depth-first search.

All of the generated types (there are both classes and enums) are within five namespaces, so I can simply check for that with SomeType.Namespace == "mynamespace". There are no cyclical dependencies or compositions—all of the classes are contain instance variables of types which are defined in the five namespaces mentioned above, and the simplest classes eventually boil down to containing a numerical/boolean primitive, a string, an enum, or a System.Collections.ObjectModel.Collection<>.

I currently have the following code:

private static readonly Assembly MyAssembly = Assembly.Load("MyLib");
private static readonly IEnumerable<Type> MyTypes = MyAssembly.GetTypes();
private static readonly IEnumerable<Type> MyClasses = MyTypes.Where(type => type.IsClass);
private static Dictionary<Type, PropertyInfo[]> MyTypePropertiesAndNames = MyClasses.ToDictionary(type => type, type => type.GetProperties());

public static void Main()
{
    GenerateAdjList();
}

public static LinkedList<string> GenerateAdjList()
{
    // what do I fill in here to return a fully-populated LinkedList?
}

I note that MyTypePropertiesAndNames is already some sort of 'adjacency-list' that isn't fully populated yet, so I was wondering how I could use that Dictionary to create a full adjacency list.

Some problems noted in the linked questions are how to handle List<>s (in my case, Collection<>s), and primitive types; I was planning to add a pair of square brackets to the dot-separated strings to signify to the user that they'd have to specify an index.


One addendum: Given a certain object with a type defined in one of the 5 namespaces, I would ideally like to generate the entire structure of the object into a Lookup<> of sorts, so that when a user specifies the name of a sub-property of the object, every possible path to that sub-property is returned.

Suppose I have the following class definitions:

public class Message 
{
    public Flight Flight {get; set;}
    // ... other properties
}

public class Flight 
{
    public Arrival Arrival {get; set;}
    public Departure Departure {get; set;}
    // ... other properties
}

public class Arrival 
{
    public Aerodrome Aerodrome {get; set;}
    // ... other properties
}

public class Departure
{
    public Aerodrome Aerodrome {get; set;}
    // ... other properties
}
...

If the user executes something like GetPropertyChains(message, "Aerodrome"), then both "message.Flight.Arrival.Aerodrome" and "message.Flight.Departure.Aerodrome" should be returned.

How might I go about solving these?


[1]These schemas are part of the ICAO FIXM 4.1 Core specification.





Aucun commentaire:

Enregistrer un commentaire