Friday, February 4, 2011

Best way to pass a large number of arguments into a configuration dialog

I've got a situation where I have a main form that pops up an advanced configuration form that just has half a dozen matched check boxes and combo boxes to select some advanced options (the check boxes to enable/disable, the combo to select a media if enabled).

If I just pass the individual settings for the check and combo boxes in to the constructor for the dialog that's obviously a dozen arguments, which seems a bit excessive.

My other obvious option would be since in the main form these settings are stored in a large IDictionary with all the other main form settings I could just pass this dictionary in and fetch it back afterward with the updated values, but my understanding is that this wouldn't really be very good coding practice.

Am I missing a good way to do this that is both efficient and good coding practice?

(this particular code is in C#, although I have a feeling a general solution would apply to other languages as well)

  • I personally would create a carrier object to store the values. You then get the nice intellisense for it, and changes to it would be quite straightforward. It would also be faster than dictionary lookups for parameter values. And of course, you get type safety. :)

    From Rob Cooper
  • Something like this should be good:

    MyConfigurationDialog dialog = new MyConfigurationDialog();
    
    //Copy the dictionary so that the dialog can't mess with our settings
    dialog.Settings = new Dictionary(existingSettings);
    
    if(DialogResult.OK == dialog.Show()) {
      //grab the settings that the dialog may have changed
      existingSettings["setting1"] = dialog.Settings["setting1"];
      existingSettings["setting2"] = dialog.Settings["setting2"];
    }
    
  • I agree with Rob Cooper. Create a class to represent your configuration, and pass that into the constructor of your form. This will also allow you to define methods on your new "config" class like "saveSettings", "LoadSettings", etc. That in turn should keep the code more maintainable in general.

    As an quick-and-dirty alternative, if you are saving these to a file somewhere, just pass the name of the file, and have your form read that at run-time.

    The first option really is the way to go though, IMO.

  • You could go with Rob's solution; that's the prettiest for development. Your "carrier object" could contain the entire IDictionary and have typed properties to help intellisense. The properties could update the IDictionary. When you're done, you can pass the carrier object back and fetch the IDictionary directly from it.

    For example, if your dictionary had key/value pair "FirstEnabled"/boolean, you could do this:

    class ContainerObject
    {
        public IDictionary<object, object> _dict;
        public ContainerObject(IDictionary<object, object> dict)
        {
            _dict = dict;
        }
    
        public bool FirstEnabled
        {
            get { return (bool) _dict["FirstEnabled"]; }
            set { _dict["FirstEnabled"] = value; }
        }
    }
    

    You can change the member "_dict" to private or protected and have a accessor function if you want.

    From Ed Schwehm

0 comments:

Post a Comment