Refactor to take either NameValueCollection and KeyValueConfigurationCollection as parameter?

Example code :

EDITED : clarified example. Sorry for any confusion.

        using System.Collections.Specialized;
        using System.Configuration;

    ...

        // get collection 1

        NameValueCollection c1 = ConfigurationManager.AppSettings;

        // get collection 2

        ExeConfigurationFileMap map = new ExeConfigurationFileMap();
        map.ExeConfigFilename = "c:\\SomeConfigFile.config";
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
        KeyValueConfigurationCollection c2 = config.AppSettings.Settings;

        // do something with collections

        DoSomethingWithCollection(c1);
        DoSomethingWithCollection(c2);
...

    private void DoSomethingWithCollection(KeyValueConfigurationCollection c)
    {
        foreach(KeyValueConfigurationElement el in c)
        {
            string key = el.Key;
            string val = el.Value;
            // do something with key and value
        }
    }

    private void DoSomethingWithCollection(NameValueCollection c)
    {
        for(int i=0; i < c.Count; i++)
        {
            string key = c.GetKey(i);
            string val = c.Get(i);
            // do something with key and value
        }
    }

There are currently two versions of DoSomethingWithCollection to take either a NameValueCollection or KeyValueConfigurationCollection.

Is there a cleaner way of doing this, so that there is just one version of DoSomethingWithCollection ?

Thanks.

Answers


Well, DoSomethingWithCollection should accept two parameters - 1) ICollection/IEnumerable that will allow you to enumerate through all values 2) Delegate that will take the object and give you key and value back. So you need to essentially write two different methods to parse the item for both type of collections.

Edit: A sample code to give an idea.

delegate void KeyValueItemParser(object item, out string key, out string value);

void DoSomethingWithCollection(ICollection items, KeyValueItemParser parser)
{

   string key, value
   foreach(object item in items)
   {
      parser(item, out key, out value);
      // do whatever you want to with key & value
   }
}

Edit 2: Not sure what you mean by not needing a delegate - if you need to have one version of DoSomethingWithCollection, you need to have at least some code that work different across both collection. Delegate would be the simplest way. Another way would be define an interface that will provide a collection/enumeration of NamedValuePair/KeyValuePair and then write to wrapper classes implementing this interface for different kind of target collections. Template code would be

interface IKeyValuePairCollection
{
  int Count {get; }
  KeyValuePair<string, string> Item(int index) { get; }
}

class NamedValueCollectionWrapper : IKeyValuePairCollection
{

   private NamedValueCollection _inner;

   public NamedValueCollectionWrapper(NamedValueCollection target) 
   {
     -inner = target;
   }

   // roll out ur implementation to IKeyValuePairCollection
}

class KeyValueConfigurationCollectionWrapper : IKeyValuePairCollection
{
  ...
}

IMO, a too much work for a simple requirement.


You could write two overloads of DoSomethingWithCollection, one that takes a NameValueCollection and another that takes a KeyValueConfigurationCollection. Then, each of those overloads iterates over the collection, passing the key and value to a third method that performs whatever you want to do.


As far as both collections NameValueCollection and KeyValueConfigurationCollection implements both ICollection and IEnumerable you can do next:

private void DoSomethingWithCollection(ICollection collection)
// private void DoSomethingWithCollection(IEnumerable collection)
{
    NameValueCollection nv;
    KeyValueConfigurationCollection kvc;
    if ((nv = collection as NameValueCollection) != null)
    {
        // do stuff directly or call iterate and call 3rd method
    }
    else if ((kvc = collection as KeyValueConfigurationCollection) != null)
    {
        // do stuff directly or call iterate and call 3rd method
    }
}

Need Your Help

Compare first word of each line and replace if statement is true (Python)

python python-3.x

I'm trying to make a script which reads only the first word of each line and store them. Once the first word is a **, it gets replaced by the last sensible stored word. Doesn't matter if it's from ...

Facebook like button does not display correctly in IE7

internet-explorer-7 cross-browser facebook-like

I am using a like button from different social media site like g+, facebook like, xing, and twitter. Facebook like button works find in all browsers except in IE7. It displays like this image below...