Я ценю нахождение ответа Джоэла - сэкономил мне время! Однако мне пришлось внести несколько изменений, чтобы метод сделал то, что ожидал бы большинство пользователей:
- Я удалил ключевое слово this, предшествующее первому аргументу. Здесь он ничего не делает (хотя это может быть полезно, если метод предназначен для использования в качестве метода расширения, в этом случае он должен быть общедоступным и содержаться в статическом классе, а сам по себе быть статическим методом).
- Я сделал регулярное выражение независимым от регистра, чтобы соответствовать стандартному поведению подстановочных знаков Windows (например, "c *. *" И "C *. *" Оба возвращают один и тот же результат).
- Я добавил начальные и конечные якоря к регулярному выражению, опять же, чтобы соответствовать стандартному поведению подстановочных знаков Windows (например, «stuff.txt» будет соответствовать «stuff *» или «s *» или «s *. *», Но не просто "с").
private bool FitsMask(string fileName, string fileMask)
{
Regex mask = new Regex(
'^' +
fileMask
.Replace(".", "[.]")
.Replace("*", ".*")
.Replace("?", ".")
+ '$',
RegexOptions.IgnoreCase);
return mask.IsMatch(fileName);
}
2009.11.04 Обновление: соответствует одной из нескольких масок
Для еще большей гибкости, здесь используется метод, совместимый со штекерами, поверх оригинала. Эта версия позволяет передавать несколько масок (отсюда и множественное число в имени второго параметра fileMasks ), разделенных строками, запятыми, вертикальными чертами или пробелами. Я хотел, чтобы я мог позволить пользователю разместить столько вариантов, сколько нужно, в ListBox, а затем выбрать все файлы, соответствующие любым из них. Обратите внимание, что некоторые элементы управления (например, ListBox) используют CR-LF для разрыва строки, в то время как другие (например, RichTextBox) используют только LF - поэтому в списке «Разделение» отображаются и «\ r \ n», и «\ n».
private bool FitsOneOfMultipleMasks(string fileName, string fileMasks)
{
return fileMasks
.Split(new string[] {"\r\n", "\n", ",", "|", " "},
StringSplitOptions.RemoveEmptyEntries)
.Any(fileMask => FitsMask(fileName, fileMask));
}
2009.11.17 Обновление: более изящная обработка ввода fileMask
Более ранняя версия FitsMask (которую я оставил для сравнения) справляется со своей задачей, но, поскольку мы рассматриваем ее как регулярное выражение, она выдаст исключение, если оно не является допустимым регулярным выражением, когда оно входит. Решение состоит в том, что мы действительно хотим, чтобы любые метасимволы регулярных выражений во входной fileMask считались литералами, а не метасимволами. Но нам все еще нужно обращаться с точкой, звездочкой и знаком вопроса. Таким образом, эта улучшенная версия FitsMask безопасно удаляет эти три символа, преобразует все оставшиеся метасимволы в литералы, а затем возвращает три интересных символа обратно в их форму "regex'ed".
Еще одно незначительное улучшение - это независимость от регистра для стандартного поведения Windows.
private bool FitsMask(string fileName, string fileMask)
{
string pattern =
'^' +
Regex.Escape(fileMask.Replace(".", "__DOT__")
.Replace("*", "__STAR__")
.Replace("?", "__QM__"))
.Replace("__DOT__", "[.]")
.Replace("__STAR__", ".*")
.Replace("__QM__", ".")
+ '$';
return new Regex(pattern, RegexOptions.IgnoreCase).IsMatch(fileName);
}
2010.09.30 Обновление: где-то на этом пути началась страсть ...
Я был упущен, когда не обновлял это ранее, но эти ссылки, вероятно, будут интересны читателям, которые добрались до этой точки:
- Я встроил метод FitsMask в качестве основы пользовательского элемента управления WinForms, который называется FileMask - см. API здесь .
- Затем я написал статью о элементе управления FileMask, опубликованную на Simple-Talk.com, под названием Использование лямбда-выражений LINQ для разработки настраиваемых общих компонентов . (Хотя сам метод не использует LINQ, пользовательский элемент управления FileMask делает это, отсюда и название статьи.)