代码之家  ›  专栏  ›  技术社区  ›  WestDiscGolf

从字符串表示访问对象属性

  •  2
  • WestDiscGolf  · 技术社区  · 16 年前

    我有一个自定义对象(为了便于理解,只提供示例代码)。。。

    public class MyClass
    {
        private string name;
        private int increment;
        private Guid id;
    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        public int Increment
        {
            get { return increment; }
            set { increment = value; }
        }
    
        public Guid Id
        {
            get { return id; }
            set { id = value; }
        }
    }
    

    public class MyClassCollection : Collection<MyClass>
    {
    
    }
    

    我想为集合编写一个排序例程,它将具有以下公共方法。。。

        public void Sort(params string[] sortProperties)
        {
            if (sortProperties == null)
            {
                throw new ArgumentNullException("sortProperties", "Parameter must not be null");
            }
    
            if ((sortProperties.Length > 0) && (Items.Count > 1))
            {
                foreach (string s in sortProperties)
                {
            // call private sort method
                    Sort(s);
                }
            }
        }
    

    ... 私有排序方法将采用属性名称的参数。。。

        private void Sort(string propertyName)
        {
    
        }
    

    我想做的是能够将一组属性名传递到方法中。。。

            MyClassCollection current = new MyClassCollection();
    
            // setup a objects in the collection
            current = GetCollectionData();
    
            // sort by Name, then by Increment
            current.Sort("Name", "Increment");
    

    使用传递到方法中的属性名,我希望能够检查它是否具有该名称的属性,如果有,请确定它是什么类型,然后对其进行排序。

    我目前的临时解决办法是。。。

        private void Sort(string propertyName)
        {
            // convert to List
            List<MyClass> myCurrentClass = Items as List<MyClass>;
    
            // sort
            if (myCurrentClass != null)
            {
                switch (propertyName)
                {
                    case "Name":
                        myCurrentClass.Sort(delegate(MyClass myClassOne, MyClass myClassTwo)
                                     {
                                         return
                                             Comparer<string>.Default.Compare(myClassOne.Name,
                                                                              myClassTwo.Name);
                                     }
                            );
                        break;
    
                    case "Increment":
                        myCurrentClass.Sort(delegate(MyClass myClassOne, MyClass myClassTwo)
                                     {
                                         return
                                             Comparer<int>.Default.Compare(myClassOne.Increment,
                                                                           myClassTwo.Increment);
                                     });
                        break;
                }
            }
        }
    

    这可能吗?如果是,怎么办?!

    干杯

    3 回复  |  直到 16 年前
        1
  •  3
  •   Jon Skeet    16 年前

    反思将是一种方式——看 Type.GetProperty(string name) . 在此之后,创建正确的比较器可能会很棘手-您可能希望编写一个泛型方法,然后根据属性类型使用反射调用该方法。我担心这一切都会变得很糟糕,但这绝对是可行的。

        2
  •  3
  •   Frederik Gheysels    16 年前
    private void Sort( string propertyName )
    {
       List<MyClass> myCurClass = ...
    
       myCurClass.Sort(delegate( MyClass left, MyClass right ){
    
          PropertyInfo lp = typeof(MyClass).GetProperty (propertyName);
    
          Comparer.Default.Compare (pi.GetValue(left), pi.GetValue(right));
    
    
       });
    }
    

    (没有经过测试,也没有经过编译,但你会明白的)

        3
  •  1
  •   WestDiscGolf    16 年前

    昨晚我在回家的火车上对这个问题进行了一段时间的思考,希望能找到一个答案。结合使用Jon的指针和Frederik对PropertyInfo类的使用,并保持打开底层对象类型的原始想法,这就是我想到的。。。

        private void Sort_version2(string propertyName)
        {
            // convert to list
            List<MyClass> myCurrentClass = Items as List<MyClass>;
    
            string typeOfProperty;
            PropertyInfo pi;
    
            // sort
            if ((myCurrentClass != null) && (MyClass.HasDetailAndExtract(propertyName, out typeOfProperty, out pi)))
            {
                switch(typeOfProperty)
                {
                    case "System.String":
                        myCurrentClass.Sort(delegate(MyClass one, MyClass two)
                                                {
                                                    return
                                                        Comparer<string>.Default.Compare(pi.GetValue(one, null).ToString(),
                                                                                         pi.GetValue(two, null).ToString());
                                                });
                        break;
    
                    case "System.Int32":
                        myCurrentClass.Sort(delegate (MyClass one, MyClass two)
                                                {
                                                    return
                                                        Comparer<int>.Default.Compare(
                                                            Convert.ToInt32(pi.GetValue(one, null)),
                                                            Convert.ToInt32(pi.GetValue(two, null)));
                                                });
                        break;
                    default:
                        throw new NotImplementedException("Type of property not implemented yet");
                }
            }
        }
    

    我已经记录了思考的过程和更多的细节 my blog

    感谢乔恩和弗雷德里克的帮助:-)