Publishing to a WordPress Blog via XML-RPC (Part 3)

Please refer to this post for some background.

OK, this post is going to talk about some of the plumbing. When you are sending requests to the server and when the server is replying with responses, you need to deal with key-value pairs. For example, userName = “steve” or password = “abc123″. C# has some classes that allow you to handle these, but none that I could find would store duplicate keys.

For example, let’s say you were retrieving information about a blog post, and that post had multiple categories. The server would respond with XML for each category that was identical other than the category names and IDs being different.

So I created a simple class that would allow you to store key-value pairs and have duplicates. It also allows you to retrieve those values. It also has some extra functionality that allows you to iterate over the values in it, etc.

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
 
namespace Piccolo.Common
{
	public class KeyValuePairs : IEnumerable<KeyValuePair<string, string>>
	{
		private List<string> _keys = new List<string>();
		private List<string> _values = new List<string>();
 
		public int Count
		{
			get { return _keys.Count; }
		}
 
		public void Add(string key, string value)
		{
			_keys.Add(key);
			_values.Add(value);
		}
 
		public string GetFirstValue(string key)
		{
			return _values[_keys.IndexOf(key)];
		}
 
		public string[] GetValuesMatchingKey(string key)
		{
			List<string> values = new List<string>();
 
			for (int i = 0; i < _keys.Count; i++)
				if (_keys[i] == key)
					values.Add(_values[i]);
 
			return values.ToArray();
		}
 
		public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
		{
		    return new KeyValuePairsEnumerator(_keys, _values);
		}
 
		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
 
		protected class KeyValuePairsEnumerator : IEnumerator<KeyValuePair<string, string>>
		{
			private List<string> _keys;
			private List<string> _values;
			private int _currentIndex;
 
			public KeyValuePairsEnumerator(List<string> keys, List<string> values)
			{
				_keys = new List<string>(keys);
				_values = new List<string>(values);
 
				Reset();
			}
 
			public KeyValuePair<string, string> Current
			{
				get { return new KeyValuePair<string, string>(_keys[_currentIndex], _values[_currentIndex]); }
			}
 
			public void Dispose() {}
 
			object IEnumerator.Current
			{
				get { return Current; }
			}
 
			public bool MoveNext()
			{
				_currentIndex++;
				return _currentIndex < _keys.Count;
			}
 
			public void Reset()
			{
				_currentIndex = -1;
			}
		}
	}
}

I also wanted to test this class to make sure it would behave in a way that I expected. So I created some nUnit tests for this. These tests also illustrate how you might use this class.

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
 
namespace Piccolo.Common.Tests
{
	[TestFixture]
	public class KeyValuePairsTests
	{
		private KeyValuePairs _testPairs;
 
		[SetUp]
		public void SetUpFixture()
		{
			_testPairs = new KeyValuePairs();
			_testPairs.Add("abc", "123");
			_testPairs.Add("abc", "123");
			_testPairs.Add("abc", "456");
			_testPairs.Add("def", "456");
		}
 
		[Test]
		public void Count()
		{
			Assert.AreEqual(4, _testPairs.Count);
		}
 
		[Test]
		public void Iterate()
		{
			int count = 0;
			foreach (KeyValuePair<string, string> pair in _testPairs)
			{
				if (count < 3)
					Assert.AreEqual("abc", pair.Key);
				else
					Assert.AreEqual("def", pair.Key);
 
				if (count < 2)
					Assert.AreEqual("123", pair.Value);
				else
					Assert.AreEqual("456", pair.Value);
 
				count++;
			}
		}
 
		[Test]
		public void GetFirstValue()
		{
			Assert.AreEqual("123", _testPairs.GetFirstValue("abc"));
			Assert.AreEqual("456", _testPairs.GetFirstValue("def"));
		}
 
		[Test]
		public void GetValuesMatchingKey()
		{
			Assert.Contains("123", _testPairs.GetValuesMatchingKey("abc"));
			Assert.Contains("456", _testPairs.GetValuesMatchingKey("abc"));
			Assert.Contains("456", _testPairs.GetValuesMatchingKey("def"));
		}
	}
}

Leave a Reply