У меня есть пользовательский объект (пример только кода для простоты понимания)...
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 и т.д.) и использовать различное количество вызовов делегатов для типов сортировки. Я огляделся, но я не нашел ничего, что указывает на меня в правильном направлении. Я взглянул на размышления, но я не мог видеть ничего, что могло бы мне помочь.
Возможно ли это? и если да, то как?!
Ура!
Когда я прошлой ночью ударился головой о проблему и надеялся на поезд домой, я решил, что попробую и 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");
}
}
}
Я документировал мыслительный процесс и более подробную информацию о мой блог, дайте мне знать, что вы думаете!
Спасибо Джону и Фредерику за помощь: -)
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));
});
}
Я думаю, это должно начаться.:) (Не тестировался и не компилировался, но вы получите идею)
Отражение - это путь - посмотрите Type.GetProperty(string name)
. Создание правильного компаратора может быть сложным после этого - вы можете написать общий метод, а затем вызвать это с отражением на основе типа свойства. Боюсь, все это становится довольно неприятно, но это определенно возможно.