1

Is there a way to deserialize user.config in a different assembly? I need a form bound to Properties.Settings and then a service accessing these settings.

I've tried ConfigurationManager which loads the config fine, but there seems to be some kind of protection keeping the userSettings section out of my reach.

Another thing that failed so far is XmlSerializer which I'm not sure it can be mapped to the config file structure.

Mark Toman
  • 3,090
  • 2
  • 17
  • 18

1 Answers1

1

I've used something like to read a user.config file using the built in XmlTextReader.

But let me also say, that it seems like a bad design to couple your service and UI using a text file especially a user config file which in mind is susceptible to be filled with unexpected values (e.g. a user could enter a wrong value by mistake and then close the UI leaving the bad value in the config file).

If you tell me a little more about your application I can recommend a better approach.

          XmlTextReader reader = new XmlTextReader(filename);
            {
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Text:
                            switch (settingKey) //Do something
                            {

Update:

The issue with your approach is the it violates the principle of "separation of concerns" because changing your UI will change your model (on the UI app) which will then by out of sync with the model on your service. This is the way user.config is suppose to work because it's not generally used to store data that is shared between applications (that's how config files are generally used) so it does some magic behind the scenes to make it easy to setup.

This is how I would do it instead.

Let's say you have a model called Employee: (borrowing code from here)

[XmlRoot("employee")]
public class EmployeesModel
{
    [Required]
    [DisplayName("Name: ")]
    [XmlElement("employeeName")]
    public string employeeName { get; set; }

    [Required]
    [DisplayName("Position: ")]
    [XmlElement("employeePosition")]
    public string employeePosition { get; set; }

    //etc
}

You can de-serialize your XML into this a new instance of this model using something like this:

var serializer = new XmlSerializer(typeof(EmployeesModel));
employee anEmployee = 
    from xml in xmlDoc.Descendants("employee")
    select serializer.Deserialize(xml.CreateReader()) as EmployeesModel;

Now in your service you can work with an EmployeesModel instance from your XML.

In your GUI, you could just be really careful to use the same field names as your model so that your user.config XML will match your model. E.g. if you change your "employeeName" Textbox in your GUI then your GUI will still work fine, but it will serialize the control to the new name and then it will break your service.

It avoid this tight coupling where you can easily break things I would bind your employeeName Textbox directly to the model doing something like this using INotifyPropertyChanged. Data binding is very involved so you might want to read up on it here.

That why you can't inadvertently change your model while messing with the UI because the UI will no longer bind correctly and you'll get a compile error.

You then still have to serialize your controls (e.g. when your UI is closed), but that's easy because those Textbox's and other controls are bound to the model. So all you have to do is:

   XmlSerializer xmlserializer = new XmlSerializer(EmployeesModel);
    StringWriter stringWriter = new StringWriter();
    XmlWriter writer = XmlWriter.Create(stringWriter);

    xmlserializer.Serialize(writer, anEmployee); //this is your model instance from above

    serializeXml = stringWriter.ToString();

    writer.Close();

I hope that helps.

Community
  • 1
  • 1
Charlie
  • 2,004
  • 6
  • 20
  • 40
  • The UI validates the input. I'm currently using my settings class which I can serialize/deserialize. The advantage of the built in settings is they can be easily bound to controls, automatically populate them with the stored values, it can be checked whether in sync etc. I certainly want to avoid reading the settings as an xml. – Mark Toman Jun 17 '15 at 19:46
  • But if your service doesn't have any controls you have this imbalance where the controls are bound to a text file and then your text file has to be bound to some custom type in the service. In my opinion, it would be better to create 1 interface to the text file and then bind your controls or other types to that interface. I can update my answer to explain more if that would be helpful. I don't see how you can avoid XML - the config file is XML. – Charlie Jun 17 '15 at 19:52
  • I don't want to avoid xml as a serialization format, I want to avoid reading it as xml. I'm not sure what you mean by binding the controls to an interface, just to clarify, the service is a headless process without any interface. – Mark Toman Jun 17 '15 at 20:23
  • Thanks for pointing me in the right direction. Fortunately custom databinding is useful even without implementing `INotifyPropertyChanged` which makes it also competitive with the built in settings in terms of productivity. – Mark Toman Jun 18 '15 at 00:34
  • My hope in writing out that answer is to help readers think through the design principles and not just rely on behind the scenes magic. If you do come up with a code snippet that works well please post it for future readers. – Charlie Jun 18 '15 at 13:58