I've got a custom object (example only code for ease of understanding) ...
我有一个自定义对象(示例仅为了便于理解的代码)...
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; }
}
}
... and a custom collection of this class ...
......以及这个班级的自定义集合......
public class MyClassCollection : Collection<MyClass>
{
}
I was looking to write a Sort routine for the collection which will have the following public method ...
我正在寻找为该集合编写一个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);
}
}
}
... and the private Sort method would take a parameter of the property name ...
...并且私有Sort方法将采用属性名称的参数...
private void Sort(string propertyName)
{
}
What I want to do is be able to pass in a set of property names into the method ...
我想要做的是能够将一组属性名称传递给方法...
MyClassCollection current = new MyClassCollection();
// setup a objects in the collection
current = GetCollectionData();
// sort by Name, then by Increment
current.Sort("Name", "Increment");
Using the property names passed into the method I want to be able to check to see if it has a property of that name, if so work out what type it is and then run through a sort of it.
使用传递给方法的属性名称,我希望能够检查它是否具有该名称的属性,如果是,则确定它是什么类型然后运行它的一种。
The interim workaround which I have currently got is ...
我目前得到的临时解决方案是......
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;
}
}
}
... but ideally I would like to switch on the underlying type of the Property (string, int etc.) and using a distinct number of delegate calls for the types for sorting. I've looked around but I've not found anything which points me in the right direction. I've had a look at reflection but I couldn't see anything which would be able to help me.
...但理想情况下,我想打开属性的基础类型(字符串,int等),并使用不同数量的委托调用来进行排序。我环顾四周,但我找不到任何指向正确方向的东西。我看过反射但我看不到任何可以帮助我的东西。
Is this even possible? and if so, how?!
这有可能吗?若然,怎么样?!
Cheers!
3 个解决方案
#1
Reflection would be the way to go - look at Type.GetProperty(string name)
. Creating the right comparer might be tricky after that - you might want to write a generic method, and then invoke that with reflection based on the property type. It all gets pretty icky, I'm afraid - but it's definitely feasible.
反思将是要走的路 - 看看Type.GetProperty(字符串名称)。之后创建正确的比较器可能会很棘手 - 您可能希望编写泛型方法,然后根据属性类型使用反射调用该方法。这一切都变得非常狡猾,我担心 - 但这绝对可行。
#2
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));
});
}
I think this should get you started. :) (Not tested, nor compiled, but you'll get the idea)
我认为这应该让你开始。 :)(没有测试,也没有编译,但你会得到这个想法)
#3
After hitting my head against the problem for a while and hoping on a train home last night I decided that I would try and bash out an answer. Using a combination of Jon's pointers and Frederik's use of the PropertyInfo class and keeping the original idea of switching on the underlying object type, this is what I came up with ...
在我的头撞到这个问题一段时间并希望昨晚在火车回家后,我决定尝试抨击答案。使用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");
}
}
}
I've documented the thought process and more details on my blog let me know what you think!
我已经记录了思考过程,我博客上的更多细节让我知道你的想法!
Thanks to Jon and Frederik for the help :-)
感谢Jon和Frederik的帮助:-)
#1
Reflection would be the way to go - look at Type.GetProperty(string name)
. Creating the right comparer might be tricky after that - you might want to write a generic method, and then invoke that with reflection based on the property type. It all gets pretty icky, I'm afraid - but it's definitely feasible.
反思将是要走的路 - 看看Type.GetProperty(字符串名称)。之后创建正确的比较器可能会很棘手 - 您可能希望编写泛型方法,然后根据属性类型使用反射调用该方法。这一切都变得非常狡猾,我担心 - 但这绝对可行。
#2
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));
});
}
I think this should get you started. :) (Not tested, nor compiled, but you'll get the idea)
我认为这应该让你开始。 :)(没有测试,也没有编译,但你会得到这个想法)
#3
After hitting my head against the problem for a while and hoping on a train home last night I decided that I would try and bash out an answer. Using a combination of Jon's pointers and Frederik's use of the PropertyInfo class and keeping the original idea of switching on the underlying object type, this is what I came up with ...
在我的头撞到这个问题一段时间并希望昨晚在火车回家后,我决定尝试抨击答案。使用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");
}
}
}
I've documented the thought process and more details on my blog let me know what you think!
我已经记录了思考过程,我博客上的更多细节让我知道你的想法!
Thanks to Jon and Frederik for the help :-)
感谢Jon和Frederik的帮助:-)