Доступ к свойствам объекта из строковых представлений

2

У меня есть пользовательский объект (пример только кода для простоты понимания)...

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

... но в идеале я хотел бы включить базовый тип свойства (string, int и т.д.) и использовать различное количество вызовов делегатов для типов сортировки. Я огляделся, но я не нашел ничего, что указывает на меня в правильном направлении. Я взглянул на размышления, но я не мог видеть ничего, что могло бы мне помочь.

Возможно ли это? и если да, то как?!

Ура!

Теги:
generics
reflection
sorting

3 ответа

1
Лучший ответ

Когда я прошлой ночью ударился головой о проблему и надеялся на поезд домой, я решил, что попробую и bash ответ. Используя комбинацию указателей Джона и использования Фредериком класса 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");
            }
        }
    }

Я документировал мыслительный процесс и более подробную информацию о мой блог, дайте мне знать, что вы думаете!

Спасибо Джону и Фредерику за помощь: -)

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


   });
}

Я думаю, это должно начаться.:) (Не тестировался и не компилировался, но вы получите идею)

  • 0
    +1 Спасибо за ваши указатели! Дайте мне знать, что вы думаете о предложенном мной решении.
3

Отражение - это путь - посмотрите Type.GetProperty(string name). Создание правильного компаратора может быть сложным после этого - вы можете написать общий метод, а затем вызвать это с отражением на основе типа свойства. Боюсь, все это становится довольно неприятно, но это определенно возможно.

  • 0
    Не могли бы вы использовать обычный, не универсальный Comparer, который принимает объекты в качестве аргументов?
  • 0
    Возможно. не могу сказать, что я когда-либо использовал неуниверсальную форму - даже не знал о ее существовании!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню