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

时间:2009-01-26 14:35:54

标签: c# generics reflection sorting

我有一个自定义对象(仅为了便于理解而使用示例代码)...

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>
{

}

我正在为集合编写一个Sort例程,它将具有以下公共方法......

    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);
            }
        }
    }

...私有Sort方法将获取属性名称的参数...

    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;
            }
        }
    }

...但理想情况下,我想打开Property的基础类型(string,int等),并使用不同数量的委托调用来进行排序。我环顾四周,但我找不到任何能指向正确方向的东西。我看过反射,但是看不到任何可以帮助我的东西。

这甚至可能吗?如果是的话,怎么样?!

干杯!

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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));


   });
}

我认为这应该让你开始。 :) (没有测试,也没有编译,但你会得到这个想法)

答案 2 :(得分:1)

在我的头撞到这个问题一段时间后,希望昨晚在火车上回家我决定尝试抨击答案。使用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的思考过程和更多细节让我知道你的想法!

感谢Jon和Frederik的帮助: - )