-
-
Save DavidBurela/3074954 to your computer and use it in GitHub Desktop.
Portable task wrappers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This shows how you can create a portable task wrapper so that code in a portable library | |
// can run against async APIs for Metro style apps as well as synchronous APIs for platforms | |
// such as WP7. | |
using System; | |
namespace PortableTasks | |
{ | |
// Basic interfaces which abstract an operation which may or may not be async | |
public interface IPortableTask | |
{ | |
void ContinueWith(Action continuation, Action<Exception> error); | |
} | |
public interface IPortableTask<T> | |
{ | |
void ContinueWith(Action<T> continuation, Action<Exception> error); | |
} | |
// Implementations of the IPortableTask interfaces for operations which complete synchronously | |
public class SynchronousPortableTask : IPortableTask | |
{ | |
public void ContinueWith(Action continuation, Action<Exception> error) | |
{ | |
continuation(); | |
} | |
} | |
public class SynchronousPortableTaskFailure : IPortableTask | |
{ | |
Exception _exception; | |
public SynchronousPortableTaskFailure(Exception exception) | |
{ | |
_exception = exception; | |
} | |
public void ContinueWith(Action continuation, Action<Exception> error) | |
{ | |
error(_exception); | |
} | |
} | |
public class SynchronousPortableTask<T> : IPortableTask<T> | |
{ | |
T _result; | |
public SynchronousPortableTask(T result) | |
{ | |
this._result = result; | |
} | |
public void ContinueWith(Action<T> continuation, Action<Exception> error) | |
{ | |
continuation(_result); | |
} | |
} | |
public class SynchronousPortableTaskFailure<T> : IPortableTask<T> | |
{ | |
Exception _exception; | |
public SynchronousPortableTaskFailure(Exception exception) | |
{ | |
_exception = exception; | |
} | |
public void ContinueWith(Action<T> continuation, Action<Exception> error) | |
{ | |
error(_exception); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An implementation of IPortableTask which wraps an actual Task. | |
// This has to go in a project targeting a platform or platforms which support Task and async/await | |
using System; | |
using System.Threading.Tasks; | |
namespace PortableTasks | |
{ | |
public class AsyncPortableTask : IPortableTask | |
{ | |
Task _task; | |
public AsyncPortableTask(Task task) | |
{ | |
this._task = task; | |
} | |
public async void ContinueWith(Action continuation, Action<Exception> error) | |
{ | |
try | |
{ | |
await _task; | |
} | |
catch (Exception ex) | |
{ | |
error(ex); | |
return; | |
} | |
continuation(); | |
} | |
} | |
public class AsyncPortableTask<T> : IPortableTask<T> | |
{ | |
Task<T> _task; | |
public AsyncPortableTask(Task<T> task) | |
{ | |
this._task = task; | |
} | |
public async void ContinueWith(Action<T> continuation, Action<Exception> error) | |
{ | |
T result; | |
try | |
{ | |
result = await _task; | |
} | |
catch (Exception ex) | |
{ | |
error(ex); | |
return; | |
} | |
continuation(result); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A portable view model which demonstrates how to consume APIs which may or may not | |
// be async from portable code using the IPortableTask interfaces. | |
using System; | |
using System.ComponentModel; | |
using System.Windows.Input; | |
namespace PortableTasks | |
{ | |
public class FileStorageTestViewModel : INotifyPropertyChanged | |
{ | |
public event PropertyChangedEventHandler PropertyChanged; | |
IFileStorage _fileStorage; | |
public FileStorageTestViewModel(IFileStorage fileStorage) | |
{ | |
_fileStorage = fileStorage; | |
_filename = "test.txt"; | |
_contents = "Hello, World!"; | |
LoadCommand = new SimpleCommand(Load); | |
SaveCommand = new SimpleCommand(Save); | |
DeleteCommand = new SimpleCommand(Delete); | |
ClearCommand = new SimpleCommand(Clear); | |
} | |
string _filename; | |
public string Filename | |
{ | |
get { return _filename; } | |
set | |
{ | |
if (_filename != value) | |
{ | |
_filename = value; | |
RaisePropertyChanged("Filename"); | |
} | |
} | |
} | |
string _contents; | |
public string Contents | |
{ | |
get { return _contents; } | |
set | |
{ | |
if (_contents != value) | |
{ | |
_contents = value; | |
RaisePropertyChanged("Contents"); | |
} | |
} | |
} | |
public ICommand LoadCommand { get; private set; } | |
public ICommand SaveCommand { get; private set; } | |
public ICommand DeleteCommand { get; private set; } | |
public ICommand ClearCommand { get; private set; } | |
public void Load() | |
{ | |
_fileStorage.LoadFile(Filename).ContinueWith( | |
contents => | |
{ | |
this.Contents = contents; | |
}, | |
ex => | |
{ | |
this.Contents = ex.ToString(); | |
}); | |
} | |
public void Save() | |
{ | |
_fileStorage.SaveFile(Filename, this.Contents).ContinueWith( | |
() => | |
{ | |
}, | |
ex => | |
{ | |
this.Contents = ex.ToString(); | |
}); | |
} | |
public void Delete() | |
{ | |
_fileStorage.DeleteFile(Filename).ContinueWith( | |
() => | |
{ | |
}, | |
ex => | |
{ | |
this.Contents = ex.ToString(); | |
}); | |
} | |
public void Clear() | |
{ | |
Contents = string.Empty; | |
} | |
void RaisePropertyChanged(string propertyName) | |
{ | |
var propertyChanged = PropertyChanged; | |
if (propertyChanged != null) | |
{ | |
propertyChanged(this, new PropertyChangedEventArgs(propertyName)); | |
} | |
} | |
} | |
public class SimpleCommand : ICommand | |
{ | |
Action _action; | |
public SimpleCommand(Action action) | |
{ | |
_action = action; | |
} | |
public bool CanExecute(object parameter) | |
{ | |
return true; | |
} | |
public event EventHandler CanExecuteChanged; | |
public void Execute(object parameter) | |
{ | |
_action(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A simple portable abstraction for file save, load, and delete functionality | |
namespace PortableTasks | |
{ | |
public interface IFileStorage | |
{ | |
IPortableTask SaveFile(string filename, string contents); | |
IPortableTask<string> LoadFile(string filename); | |
IPortableTask DeleteFile(string filename); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An implementation of IFileStorage for Metro style apps, which uses the WinRT storage APIs | |
using System; | |
using System.Threading.Tasks; | |
namespace PortableTasks | |
{ | |
public class MetroFileStorage : IFileStorage | |
{ | |
public IPortableTask SaveFile(string filename, string contents) | |
{ | |
return new AsyncPortableTask(SaveFileAsync(filename, contents)); | |
} | |
public async Task SaveFileAsync(string filename, string contents) | |
{ | |
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; | |
var file = await localFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.ReplaceExisting); | |
await Windows.Storage.FileIO.WriteTextAsync(file, contents); | |
} | |
public IPortableTask<string> LoadFile(string filename) | |
{ | |
return new AsyncPortableTask<string>(LoadFileAsync(filename)); | |
} | |
public async Task<string> LoadFileAsync(string filename) | |
{ | |
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; | |
Windows.Storage.StorageFile file; | |
try | |
{ | |
file = await localFolder.GetFileAsync(filename); | |
} | |
catch | |
{ | |
// TODO: figure out what happens if the file doesn't exist, only catch that type of exception | |
return string.Empty; | |
} | |
string contents = await Windows.Storage.FileIO.ReadTextAsync(file); | |
return contents; | |
} | |
public IPortableTask DeleteFile(string filename) | |
{ | |
return new AsyncPortableTask(DeleteFileAsync(filename)); | |
} | |
public async Task DeleteFileAsync(string filename) | |
{ | |
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; | |
Windows.Storage.StorageFile file; | |
try | |
{ | |
file = await localFolder.GetFileAsync(filename); | |
} | |
catch | |
{ | |
// TODO: figure out what happens if the file doesn't exist, only catch that type of exception | |
return; | |
} | |
await file.DeleteAsync(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An implementation of IFileStorage for Windows Phone, which uses isolated storage | |
using System; | |
using System.IO; | |
using System.IO.IsolatedStorage; | |
namespace PortableTasks | |
{ | |
public class PhoneFileStorage : IFileStorage | |
{ | |
public IPortableTask SaveFile(string filename, string contents) | |
{ | |
try | |
{ | |
var userStore = IsolatedStorageFile.GetUserStoreForApplication(); | |
using (var isoFileStream = new IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, userStore)) | |
{ | |
//Write the data | |
using (var isoFileWriter = new StreamWriter(isoFileStream)) | |
{ | |
isoFileWriter.Write(contents); | |
} | |
} | |
return new SynchronousPortableTask(); | |
} | |
catch (Exception ex) | |
{ | |
return new SynchronousPortableTaskFailure(ex); | |
} | |
} | |
public IPortableTask<string> LoadFile(string filename) | |
{ | |
try | |
{ | |
var userStore = IsolatedStorageFile.GetUserStoreForApplication(); | |
using (var isoFileStream = new IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, userStore)) | |
{ | |
using (var isoFileReader = new StreamReader(isoFileStream)) | |
{ | |
string contents = isoFileReader.ReadToEnd(); | |
return new SynchronousPortableTask<string>(contents); | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
return new SynchronousPortableTaskFailure<string>(ex); | |
} | |
} | |
public IPortableTask DeleteFile(string filename) | |
{ | |
try | |
{ | |
var userStore = IsolatedStorageFile.GetUserStoreForApplication(); | |
userStore.DeleteFile(filename); | |
return new SynchronousPortableTask(); | |
} | |
catch (Exception ex) | |
{ | |
return new SynchronousPortableTaskFailure(ex); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment