I've used this ObjectPool class as the basis of my Identity Map. However, I need to bring back the list of all objects of a type. Matthew has :
public IEnumerable<T> GetItems<T>()
{
Type myType = typeof(T);
if (!m_pool.ContainsKey(myType))
return new T[0];
return m_pool[myType].Values as IEnumerable<T>;
}
However, when I make changes to the client like so:
pool.AddItem<Animal>(dog.ID, dog);
pool.AddItem<Vegetable>(carrot.Identifier, carrot);
pool.AddItem<Vegetable>(greenbean.Identifier, greenbean);
pool.AddItem<Mineral>(carbon.UniqueID, carbon);
Console.WriteLine("Dog is in the pool -- this statement is " + pool.ContainsKey<Animal>(dog.ID));
IEnumerable<Vegetable> veggies = pool.GetItems<Vegetable>();
foreach(Vegetable veg in veggies)
Console.WriteLine(string.Format("{0} - {1}", veg.Color, veg.IsTasty));
veggies is null. It would appear that m_pool[myType].Values does not support the cast to IEnumerable.
I've tried a few things, for example:
IDictionary<int, T> dic = (IDictionary<int, T>) m_pool[myType];
ICollection<T> values = (ICollection<T>)dic.Values;
However, I always end up with a casting error.
What am I missing?
-
What type exaclty is
carrot
andgreenbean
? Can you post yourAdd<>()
method? -
Well, that
GetItems
method is never going to work, seeing asDictionary<int, object>.Values
doesn't implementIEnumerable<T>
unlessT
isobject
. Shame that the method is so fundamentally broken - oh for some unit tests.I suggest you check the licence, and if you can fix
GetItems
, do so:public IEnumerable<T> GetItems<T>() { Type myType = typeof(T); IDictionary<int, object> dictionary; if (!m_pool.TryGetValue(myType, out dictionary)) { return new T[0]; } return dictionary.Values.Cast<T>(); }
That's if you're using .NET 3.5 (you'll need
using System.Linq
as well, to get theCast
extension method). Let me know if you need something for .NET 2.0.Konrad Rudolph : Any advantages of using `new T[0]` over `Enumerable.Empty()`? I'm asking merely out of curiosity. Jon Skeet : None really. I just reused as much of the code as possible :) (It was probably written pre-LINQ.) -
I use the following ObjectPool ( the code is not mine I just added couple of methods ) ( if you do not use log4net replace logger.Info with Console.WriteLine ; )
using System; using System.Collections.Generic; using System.Text; using System.Collections.Specialized; using System.Reflection; using log4net; using log4net.Config; namespace DH { //DH - DataHolders /// <summary> /// This class models a storage structure for objects queriable by id /// </summary> public class ObjectPool { #region Props private int totalCount; public int TotalCount { get { return totalCount; } } public int ID { get; set; } #endregion Props public ObjectPool () { m_pool = new Dictionary<Type, Dictionary<Int32, Object>> (); } private Dictionary<Type, Dictionary<Int32, Object>> m_pool; public void AddItem<T> ( Int32 pID, T value ) { Type myType = typeof ( T ); if (!m_pool.ContainsKey ( myType )) { m_pool.Add ( myType, new Dictionary<int, object> () ); m_pool[myType].Add ( pID, value ); totalCount++; return; } if (!m_pool[myType].ContainsKey ( pID )) { m_pool[myType].Add ( pID, value ); totalCount++; return; } m_pool[myType][pID] = value; totalCount++; //Utils.Debugger.WriteIf("Adding 1 to pool count , pool count is " + this.totalCount); } public void AddItem<T> ( T value ) { Int32 pID = totalCount ; Type myType = typeof ( T ); if (!m_pool.ContainsKey ( myType )) { m_pool.Add ( myType, new Dictionary<int, object> () ); m_pool[myType].Add ( pID, value ); totalCount++; return; } if (!m_pool[myType].ContainsKey ( pID )) { m_pool[myType].Add ( pID, value ); totalCount++; return; } m_pool[myType][pID] = value; totalCount++; //Utils.Debugger.WriteIf("Adding 1 to pool count , pool count is " + this.totalCount); } public bool RemoveItem<T> ( Int32 pID ) { Type myType = typeof ( T ); if (!m_pool.ContainsKey ( myType )) return false; if (!m_pool[myType].ContainsKey ( pID )) return false; totalCount--; return m_pool[myType].Remove ( pID ); } public bool ContainsKey<T> ( Int32 pID ) { Type myType = typeof ( T ); if (!m_pool.ContainsKey ( myType )) return false; if (!m_pool[myType].ContainsKey ( pID )) return false; return m_pool[myType].ContainsKey ( pID ); } public IEnumerable<T> GetItems<T> () { Type myType = typeof ( T ); if (!m_pool.ContainsKey ( myType )) return new T[0]; return m_pool[myType].Values as IEnumerable<T>; } /// <summary> /// Gets the item. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="pID">The p ID.</param> /// <returns></returns> /// <exception cref="KeyNotFoundException"></exception> public T GetItem<T> ( Int32 pID ) { // will throw KeyNotFoundException if either of the dictionaries // does not hold the required key return (T)m_pool[typeof ( T )][pID]; } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="strPropMetaName"> the string representation of the </param> /// <param name="strPropValue"></param> /// <returns></returns> public T GetItemByPropertyValue<T> ( String strPropMetaName , String strPropValue) { Type myType = typeof ( T ); for (int i = 0; i < this.TotalCount; i++) { if (!m_pool.ContainsKey ( myType )) { return default ( T ); } else { if (this.ContainsKey<T> ( i )) { //get an item object having the same type T item = this.GetItem<T> ( i ); //if the object has the same property -- check its value MemberInfo[] members = myType.GetMembers (); for (int j = 0; j < members.Length; j++) { logger.Info ( "members[j].Name is " + members[j].Name ); //logger.Info ( ".MemberType.ToString() " + members[j].MemberType.ToString () ); //logger.Info ( "members[j].GetType().ToString() " + members[j].GetType ().ToString () ); //logger.Info ( " members[j].ToString () is " + members[j].ToString () ); //logger.Info ( " members[j].ToString () is " + members[j] ); if (members[j].Name.ToString ().Equals ( strPropMetaName )) { FieldInfo[] fi; fi = myType.GetFields ( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance ); foreach (FieldInfo f in fi) { //logger.Info ( "f.GetValue( obj ) is " + f.GetValue ( item ) ); if ( f.GetValue ( item ).ToString().Equals(strPropValue)) return (T)m_pool[typeof ( T )][i]; else continue ; } //eof foreach } else continue; } //eof for j } //eof if else continue; } //eof else if m_pool.ContainsKey } return default ( T ); } private static readonly ILog logger = LogManager.GetLogger ( typeof ( DH.ObjectPool ) ); } //eof class pool } //eof namespace namespace PoolSample { class Program { private static readonly ILog logger = LogManager.GetLogger ( typeof ( Program ) ); public static DH.ObjectPool pool = new DH.ObjectPool (); static void Main ( string[] args ) { DOMConfigurator.Configure (); //tis configures the logger Animal dog = new Animal () { Name = "Fido", ID = 1 }; Vegetable carrot = new Vegetable { Color = "Orange", Identifier = 2, IsTasty = true }; Mineral carbon = new Mineral () { UniqueID = 3, IsPoisonousToAnimal = false , Name="some"}; HolderForStrings hfs = new HolderForStrings () { ID = 4, Value = "user_name", MetaName = "meta_nam" }; HolderForStrings hfs1 = new HolderForStrings () { ID = 5, Value = "user_name", MetaName = "hfs1" }; Mineral carbon1 = new Mineral () { UniqueID = 3, IsPoisonousToAnimal = false, Name = "some1" }; pool.AddItem ( dog ); pool.AddItem ( carrot ); pool.AddItem ( hfs ); pool.AddItem ( hfs1 ); //pool.AddItem<Animal>(dog.ID, dog); //pool.AddItem<Vegetable>(carrot.Identifier, carrot); //pool.AddItem<Mineral> ( carbon ); //pool.AddItem<HolderForStrings> ( 1, hfs ); //logger.Info("Dog is in the pool -- this statement is " + pool.ContainsKey<Animal>(dog.ID)); //logger.Info("hfs is in the pool -- this statement is " + pool.ContainsKey<HolderForStrings>(hfs.ID)); //logger.Info("The hfs value is from the poos is " + pool.GetItem<HolderForStrings>(4).Value); //logger.Info("poo.GetItems is " + pool.GetItems<HolderForStrings>()); #region while //for (int i = 0; i < pool.Count -1 ; i++) int i = 1; do { try { logger.Info ( "counting" ); logger.Info ( " i is " + i.ToString () ); if (pool.ContainsKey<Animal> ( i )) { logger.Info ( " I see animal which is " + pool.GetItem<Animal> ( i ).Name ); } if (pool.ContainsKey<Vegetable> ( i )) { logger.Info ( " I see Vegetable which is " + pool.GetItem<Vegetable> ( i ).Color ); } if (pool.ContainsKey<Mineral> ( i )) { logger.Info ( " I see Mineral which is " + pool.GetItem<Mineral> ( i ).IsPoisonousToAnimal ); } if (pool.ContainsKey<HolderForStrings> ( i )) { logger.Info ( " I see string which is " + pool.GetItem<HolderForStrings> ( i ).Value ); } //logger.Info("pool.GetItem<HolderForStrings>(4).Value); is " + pool.GetItem<Object>(i).ToString()); i = i + 1; } catch (KeyNotFoundException e) { continue; } } //eof for while (i < pool.TotalCount); #endregion while #region AddHolders ////this is the success identifier //HoldInt16 holdVerifier = new HoldInt16() //{ // ID=0 , // MetaName = "ret", // Value = 0 //}; //pool.AddItem<HoldInt16>(holdVerifier.ID, holdVerifier); //ListDictionary lidMetaName = pool.LidMetaName; ////this is the message //HoldString holdMsg = new HoldString( ref lidMetaName) //{ // ID=1, // MetaName = "msg", // Value = msg, // Title = "title" //}; //pool.AddItem<HoldString>(holdMsg.ID, holdMsg); //HoldString holdmmsg = new HoldString(ref lidMetaName) //{ // ID=2, // MetaName = "mmsg", // Value = "mmsg" , // Title = "title" //}; #endregion AddHolders //Utils.Debugger.DebugListDictionary(ref msg, "domainName", ref lidMetaName); //get the value be metaName logger.Info ( "I queried the pool by property with meta Value and value user_name " ); HolderForStrings HolderForStrings = pool.GetItemByPropertyValue<HolderForStrings> ( "MetaName", "hfs1" ); //logger.Info ( "object dump" + Utils.Log.ObjDumper.DumpObject ( HolderForStrings ) ); logger.Info ( "I found the following value for property with the name \"Name\" " ); logger.Info ( HolderForStrings.MetaName); Console.ReadLine (); } //eof Main } //eof class public class Animal { public Int32 ID { get; set; } public String Name { get; set; } } public class HolderForStrings { public Int32 ID { get; set; } public String Value { get; set; } public String MetaName { get; set; } Type ObjType = typeof ( string ); public Int32 Size { get; set; } public bool IsOptional { get; set; } public bool IsPrimaryKey { get; set; } } //eof class public class Vegetable { public Int32 Identifier { get; set; } public String Color { get; set; } public Boolean IsTasty { get; set; } } public class Mineral { public Int32 UniqueID { get; set; } public Boolean IsPoisonousToAnimal { get; set; } public String Name { get; set; } } #region classObjectPool //public class ObjectPool //{ // public int Count // { // get { return m_pool.Count; } // } // public ObjectPool () // { // m_pool = new Dictionary<Type, Dictionary<Int32, Object>> (); // } // private Dictionary<Type, Dictionary<Int32, Object>> m_pool; // public void AddItem<T> ( Int32 pID, T value ) // { // Type myType = typeof ( T ); // if (!m_pool.ContainsKey ( myType )) // { // m_pool.Add ( myType, new Dictionary<int, object> () ); // m_pool[myType].Add ( pID, value ); // return; // } // if (!m_pool[myType].ContainsKey ( pID )) // { // m_pool[myType].Add ( pID, value ); // return; // } // m_pool[myType][pID] = value; // } // public bool RemoveItem<T> ( Int32 pID ) // { // Type myType = typeof ( T ); // if (!m_pool.ContainsKey ( myType )) // return false; // if (!m_pool[myType].ContainsKey ( pID )) // return false; // return m_pool[myType].Remove ( pID ); // } // public bool ContainsKey<T> ( Int32 pID ) // { // Type myType = typeof ( T ); // if (!m_pool.ContainsKey ( myType )) // return false; // if (!m_pool[myType].ContainsKey ( pID )) // return false; // return m_pool[myType].ContainsKey ( pID ); // } // public IEnumerable<T> GetItems<T> () // { // Type myType = typeof ( T ); // if (!m_pool.ContainsKey ( myType )) // return new T[0]; // return m_pool[myType].Values as IEnumerable<T>; // } // /// <summary> // /// Gets the item. // /// </summary> // /// <typeparam name="T"></typeparam> // /// <param name="pID">The p ID.</param> // /// <returns></returns> // /// <exception cref="KeyNotFoundException"></exception> // public T GetItem<T> ( Int32 pID ) // { // // will throw KeyNotFoundException if either of the dictionaries // // does not hold the required key // return (T)m_pool[typeof ( T )][pID]; // } //} //eof pool #endregion public enum EnumType : byte { String, Int32, Boolean } } //eof program
0 comments:
Post a Comment