问题是您没有在 OrderBy 中使用参数 f
.OrderBy(f => propertyInfo.GetValue(orderByParam, null));
你让事情变得比需要的更复杂。
要求:给定一个目录的名称,以及类 FileInfo 的属性之一的名称,给我这个目录中由这个属性排序的所有文件的顺序。
我的建议是不要为此使用反射,而是为您的订购创建一个 IComparer 类。
这有几个优点。反射相当缓慢。比较器也可以用于 OrderByDescending。但最重要的优势是您可以控制要订购的 PropertyNames。
您可以拒绝按属性订购,也可以按属性拒绝Directory
订购Exists
。除了通过“长度”添加对订单的支持之外,您还可以通过“长度”/“长度”/“长度”添加对订单的支持。如果需要支持命令行输入,可以通过“-l”/“-L”添加对命令的支持
如果您创建一个比较器类,用法将是:
string directoryName = ...
// TODO: exception if directoryName null or empty
DirectoryInfo directory = new DirectoryInfo(directoryName);
if (!directory.Exists) TODO: exception
IComparer<FileInfo> comparer = ...
IEnumerable<FileInfo> files = directory.EnumerateFiles();
IEnumerable<FileInfo> orderedFiles = files.OrderBy(file => file, comparer);
IComparer 的实现相当简单:
class FileInfoComparer<TKey> : IComparer<FileInfo>
{
public static IComparer<FileInfo> Create(string propertyName)
{
// this Compare supports only property names of FileInfo
// and maybe not even all property names
switch (propertyName)
{
case "Name":
return new FileInfoComparer(fileInfo => fileInfo.Name);
case "Length":
return new FileInfoComparer(fileInfo => fileInfo.Length);
case "Extension"
return new FileInfoComparer(fileInfo => fileInfo.Extension);
...
default:
throw new NotSupportedException("Ordering by this property not supported");
// for instance: property names "Directory" "Exists"
}
}
private FileInfoComparer(Func<FileInfo, TKey> keySelector)
{
this.keySelector = keySelector;
}
private readonly Func<FileInfo, TKey> keySelector;
private readonly IComparer<TKey> keyComparer = Comparer<TKey>.Default;
public int Compare(FileInfo x, FileInfo y)
{
// TODO: decide what to do if x or y null. Exception? first or last in sort order?
return keyComparer.Compare(this.keySelector(x), this.keySelector(y));
}
}
我创建了一个私有构造函数,所以只有 Create 函数可以创建这个比较器。
用法:
var comparer = FileInfoComparer.Create("Length"); DirectoryInfo 目录 = 新 DirectoryInfo(directoryPath); var orderedFiles = directory.EnumerateFiles.Orderby(file => file, comparer);