Xamarin.Forms DependencyService не может использовать кроссплатформенный интерфейс при обработке файлов

Я следую официальному руководству Xamarin для кросс -платформенная обработка файлов с использованием проекта .net-standard-2.0 PCL. Приложение предназначено для Android и Windows.

Это вызывает у меня вопрос. Код интерфейса приведен ниже.

public interface ISaveAndLoad {
    void SaveText (string filename, string text);
    string LoadText (string filename);
}

Однако код для UWP записывается как

[assembly: Dependency(typeof(SaveAndLoad_WinApp))]
namespace WindowsApp
{
    // https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh758325.aspx
    public class SaveAndLoad_WinApp : ISaveAndLoad
    {
        public async Task SaveTextAsync(string filename, string text)
        {
            StorageFolder localFolder = ApplicationData.Current.LocalFolder;
            StorageFile sampleFile = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
            await FileIO.WriteTextAsync(sampleFile, text);
        }
        public async Task<string> LoadTextAsync(string filename)
        {
            StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
            StorageFile sampleFile = await storageFolder.GetFileAsync(filename);
            string text = await Windows.Storage.FileIO.ReadTextAsync(sampleFile);
            return text;
        }
    }
}

Код не будет компилироваться, поскольку SaveAndLoad_WinApp не реализует интерфейс ISaveAndLoad.

Я знаю, что могу изменить интерфейс на Task и Task<string>, чтобы он скомпилировался.

Однако проблемы возвращаются к Android. UWP использует эту Windows.Storage.FileIO вещь, которой нет на Android. Хотя Android использует System.IO, у него нет ожидаемого метода Async. Это означает, что я не могу поделиться интерфейсом, поскольку UWP требует async Task<string>, но Android возвращает только string вместо Task.

Если я не использую async в методе UWP, FileIO не будет работать наоборот. async void для SaveText работает нормально, как указано в интерфейсе void. Однако это не позволит мне сделать async string для LoadText, поскольку асинхронный метод должен возвращать Task<T>, Task или void.

Похоже, что путь будет заключаться в реализации async и на Android, позволяя при этом код работать синхронно. Однако мне кажется, что я сделал что-то не так, поскольку образец Xamarin показывает, что он должен работать.

Я что-то недопонимаю здесь или не хватает реализации? Или это действительно неправильно в документации Xamarin?


ОБНОВЛЕНИЕ №1. Я поставил async void вместо SaveText и понимаю, что существует проблема, заключающаяся в том, что поток не ожидается. Чтобы он быстро перешел к следующей функции. Так что мне действительно нужно дождаться функции в PCL для UWP. Однако реализация на Android - это void, чего нельзя ожидать. Так что это действительно вызывает ошибку ... Есть ли какие-нибудь предложения по реализации этого сценария?

Вот код, который я ввел в свой PCL

public static void Save(){
    DependencyService.Get<ISaveAndLoad>().SaveText("temp.txt", input.Text);
}

person Eric Lam    schedule 09.12.2017    source источник


Ответы (1)


Код не будет компилироваться, поскольку SaveAndLoad_WinApp не реализует интерфейс ISaveAndLoad.

Вы можете загрузить образец документа WorkingWithFiles, вы можете найти его здесь. В этом примере ISaveAndLoad Интерфейс немного отличается:

public interface ISaveAndLoad
{
    Task SaveTextAsync (string filename, string text);
    Task<string> LoadTextAsync (string filename);
    bool FileExists (string filename);
}

UWP использует эту вещь Windows.Storage.FileIO, которой нет на Android. Хотя Android использует System.IO, у него нет ожидаемого метода Async.

Вы можете обратиться к SaveAndLoad_Android.cs в примере проекта используйте StreamWriter.WriteAsync ():

public class SaveAndLoad_Android : ISaveAndLoad
{
    #region ISaveAndLoad implementation

    public async Task SaveTextAsync (string filename, string text)
    {
        var path = CreatePathToFile (filename);
        using (StreamWriter sw = File.CreateText (path))
            await sw.WriteAsync(text);
    }

    public async Task<string> LoadTextAsync (string filename)
    {
        var path = CreatePathToFile (filename);
        using (StreamReader sr = File.OpenText(path))
            return await sr.ReadToEndAsync();
    }

    public bool FileExists(string filename)
    {
        return File.Exists(CreatePathToFile(filename));
    }

    #endregion

    string CreatePathToFile(string filename)
    {
        var docsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        return Path.Combine(docsPath, filename);
    }
}

Затем в вашем PCL используйте SaveTextAsync. / a> метод вроде этого:

var fileService = DependencyService.Get<ISaveAndLoad> ();
...
saveButton.Clicked += async (sender, e) => 
{
    loadButton.IsEnabled = saveButton.IsEnabled = false;
    // uses the Interface defined in this project, and the implementations that must
    // be written in the iOS, Android and WinPhone app projects to do the actual file manipulation

    await fileService.SaveTextAsync (fileName, input.Text);
    loadButton.IsEnabled = saveButton.IsEnabled = true;
};
person Eren Shen    schedule 10.12.2017