简体   繁体   English

如何从通用字典中获取值列表

[英]How to get value list from generic dictionary

I've used this ObjectPool class as the basis of my Identity Map. 我已经将此ObjectPool类用作我的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. 看来m_pool [myType] .Values不支持强制转换为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? 我想念什么?

Well, that GetItems method is never going to work, seeing as Dictionary<int, object>.Values doesn't implement IEnumerable<T> unless T is object . 好吧,该GetItems方法永远不会起作用,就像Dictionary<int, object>.Values一样。除非Tobject否则Dictionary<int, object>.Values不会实现IEnumerable<T> 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: 我建议您检查许可证,如果可以修复GetItems ,请执行以下操作:

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 the Cast extension method). 那就是如果您使用的是.NET 3.5(您还需要using System.Linq ,以获取Cast扩展方法)。 Let me know if you need something for .NET 2.0. 让我知道是否需要.NET 2.0。

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 ; ) 我使用下面的ObjectPool(代码不是我的,我只是添加了几个方法)(如果您不使用log4net,请将Console.WriteLine替换为logger.Info)

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  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM