views:

659

answers:

2

I have a set of custom XML configuration management classes in .NET.

There are two configuration scopes in my application:

User: the setting applies to the user regardless of the account she's logged into. Stored in a XML config file in the user's directory.

User/Account: the setting applies to the user when logged into a particular account. Stored in a XML config file in the user's directory under an account specific sub-directory.

The two XML documents have the same structure and can be modified by hand. When the application starts up, I read the XML config from the user's profile and the XML config from the User/Account directory. I then merge the two XML documents into a single XDocument and then deserialize the XML into objects modeled after the XDocument's sections. If there is a User/Account-level setting present, it should override the User-level setting. Example:

User file:

<FileSettings>
  <DownloadPath>C:\downloads</DownloadPath>
  <UploadPath>C:\uploads</UploadPath>
</FileSettings>

User/Account file for account XYZ:

<FileSettings>
  <DownloadPath>C:\newlocation\xyz\mystuff</DownloadPath>
</FileSettings>

Result after merge:

<FileSettings>
  <DownloadPath>C:\newlocation\xyz\mystuff</DownloadPath>
  <UploadPath>C:\uploads</UploadPath>
</FileSettings>

In the above example, a FileSettings object with 2 properties - DownloadPath and UploadPath will be instantiated from the section.

Here's my issue: I have no idea which config file (i.e., scope) the DownloadPath and UploadPath came from. As a result, when the object needs to serialize again, it doesn't know which properties go in which file.

Question: What's the best way to store the "source," on a property-by-property basis, so that I can ensure a setting gets written to the same config file that it was read from?

Thanks.

+2  A: 

After merging, is it possible to append the value source of each properties?

<FileSettings>
  <DownloadPath>C:\newlocation\xyz\mystuff</DownloadPath>
  <UploadPath>C:\uploads</UploadPath>
  <DownloadPathSrc>xyz</DownloadPathSrc>
  <DownloadPathSrc>user</DownloadPathSrc>
</FileSettings>

If so, the two src properties can be deserialized into your FileSettings object, Before serialization to file again, you can create a brand new FileSetting object for each of the source WITHOUT setting the *src property, by default null string won't be serialized by XmlSerializer. With the src property, you know which file the object you want to serialize to.

EDIT, If you want to add src as attribute of the element. that was actually my intial thought too, however, you need create class for each of the property. e.g. for property DownloadPath in FileSetting class

[XmlType()]
public class DownloadPath
{ 
  [XmlAttribute]
  public string Src;   
  [XmlText]
  public string Text;
}
// serialize to
<DownloadPath Src="...">text</DownloadPath>
codemeit
This was my initial thought. I was going to do <DownloadPath src="user">C:\path</DownloadPath>. But I wasn't sure how to represent this in the object once it's deserialized. I want to avoid having a corresponding source property for every property in the object.
vg1890
Is there a way to "decorate" each property with a source attribute in object form the way we use attributes on a XML element?
vg1890
check the updated post, i added comment for src as attribute.
codemeit
+1  A: 

I would prefer add some properties to the XML like this:

<FileSettings>
   <DownloadPath src="Account">C:\newlocation\xyz\mystuff</DownloadPath>
   <UploadPath src="User">C:\uploads</UploadPath>
</FileSettings>

It's easier to implement the separation layer of the content.

Paulo Oliveira