views:

292

answers:

2

Hi,

I need to model in memory a collection web files, but that relationships between them. That is file A (e.g. html) may have a link to file B (e.g. css) and file C (e.g. javascript). Also file D may also require file B. If I wanted to delete file A I would need to make sure any files it uses (e.g. file B) is not also being used by another file (e.g. file D). Perhaps something like:

  List<WebFile> list_of_webfiles

  public class WebFile
  - string url
  - bool parentFile

  public class FileRelationship
  - private WebFile parentWebFile;
  - private WebFile childWebFile;

QUESTION - What would be the best way to model this in C#? (e.g. which collection type & how to model)

Note - it has to be modeled in memory (no database), and I need to be able to serialize to XML too to save. An example of what I mean would be something that looked like this...

        XmlSerializer serializer = new XmlSerializer(typeof(List<WebFile>));
        TextWriter textWriter = new StreamWriter(CONFIG_FILE_PATH);
        serializer.Serialize(textWriter,  list_of_webfiles);
        textWriter.Close();

Thanks

+1  A: 

This seems to imply a hierarchical 'tree' relationsihp where you may have

Class WebFile:
- URL : string
- Parent : WebFile
- Children : WebFile[] (could be a list depending on the need)

Then somewhere you have a

List<WebFile> webFiles;

This approach makes it easy to traverse the tree of webfiles and find the related ones, but harder to list all the files themselves.

Alternatively, you could store the list of files and relationships seperately

Class WebFile
- URL : string

Class WebFileRelationship
- Parent : WebFile
- Child : WebFile

And you have 2 containers

List<WebFile> webFiles;
List<WebFileRelationship> relationships;

This approach makes it easy to list all the relationships or all the files, but hard to determine the individual relationships.

It all depends on your application, do you need more information about the individual files or the relationships?

TJB
I guess I need both. The first option looks nice, but then is it more of a Hierachy map rather than Web map? For example from my original words and example would File B have two (2) instances? Or in other words, I'm trying to understand whether the "Children : WebFile[]" array contains separate instances of WebFile's, OR does it just hold a reference to an existing WebFile object already in the List?
Greg
Its just a reference, like a pointer, so you can add an existing web file to the list of 'children' without duplicating it
TJB
Also, you could omit the parent list or make it an array as well, depending on what you need. It may be useful to write up some psuedocode of what you want to achieve, and then shape the data structure accordingly.
TJB
thanks TJB - I'd be interested in your comments whether a lightweight database (e.g. sqlite) would make it a lot easier to service my requirement (e.g. to ask the structure for "give me all children files for parent file X"). Which of the two approaches would you go for noting my relatively simple requirements?
Greg
+1  A: 

The fact that you have duplicates (in terms of multiple files requiring B) means that it would be a pain to use the most obvious "requires" structure as a tree, since that would involve nesting B multiple times (from different parents). A few options:

  • keep the object-references in the object model, but only list the name (or some other reference) in the file; relatively simple to do, but requires fixups after deserialization
  • only list the name (or some other reference) in the relationship, and mirror this in the object model - i.e. "file.Parent" is a key, not another object
  • have the full object model, and use a graph serializer, such as DataContractSerializer with preserve-object-references enabled

I would probably choose between the last two; the last has "not very pretty" xml, but is relatively simple to implement. But I'd be tempted to just use the middle option, and have just the key references in the object model, i.e.

[XmlType("file"), XmlRoot("file")]
public class File {
    [XmlAttribute("name")]
    public string Name {get;set;}
    [XmlElement("ref")]
    public List<string> References {get;set;}
    public File() {References = new List<string>();}
}

maybe not pure OO, but simple to do. Also - avoid the need to duplicate data; if you store it just like the above, you can always scan to see "what uses this file" (with some indexing if you need). But trying to maintain relationships in both directions (i.e. "UsedBy") is a nightmare.

Marc Gravell
thanks Marc - if the focus is to have my simple winforms application have an easy download/install (e.g. clickonce), would you think running with your above-mentioned approach would still be preferable to looking at a light weight database such as SQLite or Firebird? (I'm still not quite sure how easy these are to bundle for download/install as part of a winforms app)...
Greg
PS. A lightweight database would still make it a lot easier to service my requirement to ask the structure for "give me all children files for parent file X" I guess? If I did the collections/xml based approach there would still be a little more work in implementing these.
Greg