My version of a SmartBag
Posted by Garry Shutler in ASP.NET MVC, SmartBag
After seeing Jeffrey Palermo's SmartBag (part 1 and part 2) I was inspired to create my own version which was more specific to my needs. For one I'm a lover of the IEnumerable<T> interface, especially when combined with the power of LINQ for Objects.
Anyway, enough of my waffle, here's the code for the class.
- using System;
- using System.Collections.Generic;
- using System.Collections;
- using System.Text;
- namespace SmartBag
- {
- public class SmartBag
- {
- private Hashtable _hashtable;
- public SmartBag()
- {
- this._hashtable = new Hashtable();
- }
- public void Add<T>(T item)
- {
- List<T> list;
- if (!this._hashtable.ContainsKey(typeof(T)))
- this._hashtable.Add(typeof(T), new List<T>());
- list = this._hashtable[typeof(T)] as List<T>;
- list.Add(item);
- }
- public IEnumerable<T> Get<T>()
- {
- if (!this._hashtable.ContainsKey(typeof(T)))
- throw new IndexOutOfRangeException(string.Format("There are no entries for {0}", typeof(T).Name));
- foreach (T item in this._hashtable[typeof(T)] as List<T>)
- yield return item;
- }
- }
- }
There are basically two methods to it, Add and Get. Add adds items of the specified type to a list of that type. Get retrieves the list of the specified type.
Below are my test cases which should give you some ideas of how you can use it.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using MbUnit.Framework;
- namespace SmartBag
- {
- [TestFixture]
- class SmartBagTest
- {
- [Test]
- public void AClassAddedAgainstAnInterfaceCanBeRetrievedTogether()
- {
- SmartBag bag = new SmartBag();
- bag.Add<IContract>(new Parent());
- bag.Add<IContract>(new Child());
- Assert.AreEqual(2, bag.Get<IContract>().Count());
- }
- [Test]
- public void AChildWillBeAddedToItsParentsEnumerationIfYouDefineIt()
- {
- SmartBag bag = new SmartBag();
- bag.Add(new Parent());
- bag.Add<Parent>(new Child());
- Assert.AreEqual(2, bag.Get<Parent>().Count());
- }
- [Test, ExpectedException(typeof(IndexOutOfRangeException))]
- public void AnExpectionWillBeRaiseWhenAttemptingToRetrieveATypeThatDoesNotExist()
- {
- SmartBag bag = new SmartBag();
- foreach (Object item in bag.Get<Object>()) { } // must enumerate for it to be evaluated
- }
- [Test]
- public void ShouldBeAbleToAddChildAsADifferentType()
- {
- SmartBag bag = new SmartBag();
- bag.Add(new Parent());
- bag.Add(new Child());
- Assert.AreEqual(1, bag.Get<Parent>().Count());
- Assert.AreEqual(1, bag.Get<Child>().Count());
- }
- private class Parent : IContract
- {
- }
- private class Child : Parent
- {
- }
- private interface IContract
- {
- }
- }
- }
To begin with this is a basic idea. I hope to utilise it in an upcoming project and it will probably look a bit different after I've used it in anger. Something I can see I might need is to extract an interface to make testing easier but I've left that out for now as YAGNI may apply.
Any feedback would be greatly appreciated.
This entry was posted on at Friday, January 25, 2008 and is filed under ASP.NET MVC, SmartBag. You can follow any responses to this entry through the RSS 2.0. You can leave a response.
