C#使用GetProperty for LINQ OrderBy使用FileInfo

问题描述 投票:1回答:2

我正在尝试使用Reflection GetProperty来动态设置我想要的OrderBy类型。 orderByParam将有一个值,如"Length""Name""CreationTime"等。这将允许我按照我想要的顺序将文件添加到列表中。我收到的错误是:

对象与目标类型不匹配

。我在这里错过了什么?

try
{
    PropertyInfo propertyInfo = typeof(FileInfo).GetProperty(orderByParam);
    var files = Directory.GetFiles(strPath)
                         .OrderBy(f => propertyInfo.GetValue(orderByParam, null));  
                         //FileInfo(f).CreationTime))

    foreach (string str in files)
    {
        strFiles.Add(Path.GetFileName(str));
    }
}
c# linq system.reflection system.io.fileinfo
2个回答
1
投票

把它作为

 PropertyInfo propertyInfo = typeof(FileInfo).GetProperty(orderByParam);

 var files = Directory
   .EnumerateFiles(strPath)
   .OrderBy(f => propertyInfo.GetValue(new FileInfo(f), null));  

既然你想要从f(确切地说是new FileInfo(f))读取属性值,而不是orderByParam


0
投票

问题是你不在OrderBy中使用参数f

.OrderBy(f => propertyInfo.GetValue(orderByParam, null)); 

你使事情变得比需要的更复杂。

要求:给定目录的名称以及类FileInfo的某个属性的名称,为我提供此属性排序的此目录中所有文件的序列。

我的建议是不要为此使用反射,而是为您的订购创建IComparer类。

这有几个优点。反思相当缓慢。比较器也可用于OrderByDescending。但最重要的优点是您可以控制要订购的PropertyNames。

您可以拒绝物业Directory或物业Exists的订购。除了通过“长度”添加对订单的支持,您可以通过“LENGTH”/“length”/“lENgth”添加对订单的支持。如果您需要支持命令行输入,可以通过“-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目录= new DirectoryInfo(directoryPath); var orderedFiles = directory.EnumerateFiles.Orderby(file => file,comparer);

© www.soinside.com 2019 - 2024. All rights reserved.