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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/730791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:56:43  来源:igfitidea点击:

How to get value list from generic dictionary

c#genericsdictionary

提问by basscinner

I've used this ObjectPoolclass as the basis of my Identity Map. However, I need to bring back the list of all objects of a type. Matthew has :

我已经使用这个ObjectPool类作为我的身份映射的基础。但是,我需要带回一个类型的所有对象的列表。马修有:

    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?

我错过了什么?

采纳答案by Jon Skeet

Well, that GetItemsmethod is nevergoing to work, seeing as Dictionary<int, object>.Valuesdoesn't implement IEnumerable<T>unless Tis object. Shame that the method is so fundamentally broken - oh for some unit tests.

好吧,该GetItems方法永远不会起作用,因为除非是,否则Dictionary<int, object>.Values不会实现。遗憾的是,该方法从根本上被破坏了 - 哦,对于某些单元测试。IEnumerable<T>Tobject

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.Linqas well, to get the Castextension method). Let me know if you need something for .NET 2.0.

如果您使用的是 .NET 3.5(您还需要using System.Linq获取Cast扩展方法)。如果您需要 .NET 2.0 的东西,请告诉我。

回答by Yordan Georgiev

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,请将 logger.Info 替换为 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