Это решает проблему:
val turnsType = object : TypeToken>() {}.type
val turns = Gson().fromJson>(pref.turns, turnsType)
Первая строка создает выражение object , которое спускается с TypeToken
, а затем получает Java Type
. Тогда методу Gson().fromJson
нужен либо тип, указанный для результата функции (который должен соответствовать созданному TypeToken
). Две версии этой работы, как указано выше, или:
val turns: List = Gson().fromJson(pref.turns, turnsType)
Чтобы упростить создание TypeToken
, вы можете создать вспомогательную функцию, которая должна быть inline так что он может использовать параметры reified type :
inline fun genericType() = object: TypeToken() {}.type
, который затем может быть использован одним из следующих способов:
val turnsType = genericType>()
// or
val turnsType: List = genericType()
И весь процесс может быть завернут в функцию расширения для экземпляра Gson
:
inline fun Gson.fromJson(json: String) = this.fromJson(json, object: TypeToken() {}.type)
Чтобы вы могли просто позвонить Gson и не беспокоиться о TypeToken
вообще:
val turns = Gson().fromJson(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
Здесь Котлин использует вывод типа с одной стороны задания или другой, и генерирует обобщенные данные для встроенной функции для прохождения через полный тип (без стирания) и используя это для построения TypeToken
, а также делает звоните в Gson
Как насчет этого? Это избегает исключения, часто выдаваемого встроенным рекурсивным поиском (т.е. Вы получаете доступ запрещен к единственной папке, и Ваш целый поиск умирает), и лениво оценен (т.е. это возвращает результаты, как только это находит их, вместо того, чтобы буферизовать результаты 2000 года). Ленивое поведение позволяет Вам создать быстро реагирующий UIs и т.д. и также работает хорошо с LINQ (особенно First()
, Take()
, и т.д.).
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
static class Program { // formatted for vertical space
static void Main() {
foreach (string match in Search("c:\\", "*.xml")) {
Console.WriteLine(match);
}
}
static IEnumerable<string> Search(string root, string searchPattern) {
Queue<string> dirs = new Queue<string>();
dirs.Enqueue(root);
while (dirs.Count > 0) {
string dir = dirs.Dequeue();
// files
string[] paths = null;
try {
paths = Directory.GetFiles(dir, searchPattern);
} catch { } // swallow
if (paths != null && paths.Length > 0) {
foreach (string file in paths) {
yield return file;
}
}
// sub-directories
paths = null;
try {
paths = Directory.GetDirectories(dir);
} catch { } // swallow
if (paths != null && paths.Length > 0) {
foreach (string subDir in paths) {
dirs.Enqueue(subDir);
}
}
}
}
}
System.IO.Directory.GetFiles(@"c:\", "*.xml", SearchOption.AllDirectories);
Похоже, библиотека recls - обозначает rec ursive ls - теперь имеет чистый .NET реализация . Я только что прочитал об этом в статье доктора Добба .
Будет использоваться как:
using Recls;
using System;
static class Program { // formatted for vertical space
static void Main() {
foreach(IEntry e in FileSearcher.Search(@"c:\", "*.xml|*.csv|*.xls")) {
Console.WriteLine(e.Path);
}
}