Windows Phone Essentials
This library is focused on making the common things you have to do in every windows phone application, like persist application settings, use tasks/choosers, log/trace, threading/asynchronous development etc. testable.
Features
Settings Provider
Out of the box the phone gives us IsolatedStorageSettings.ApplicationSettings which is not too bad, but it is static, not type safe, and relies on string based keys (meaning you need to copy/paste the string keys, or preferably define constants). The settings provider makes application settings a much nicer experience!
Start off creating a settings class, inheriting from ISettings this is a marker interface only. Then you can create properties on it, and decorate them with attributes. For example:
public class MyApplicationSettings : ISettings
{
[DisplayName("Mail Server")]
[DefaultValue("http://example.com")]
public string MailServer { get; set; }
[DefaultValue(2)]
public int NumberOfWeeksToSync { get; set; }
}
To load or save your settings:
var settingsProvider = new SettingsProvider();
var settings = settingsProvider.Load<MyApplicationSettings>();
//settings.NumberOfWeeksToSync == 2
settings.MailServer = "http://example2.net";
settingsProvider.Save(settings);
You can have as many settings classes as you want, so feel free to break settings up into logical groupings.
Settings will also be cached in the SettingsProvider to save reloading values that haven't changed from Iso storage, this means currently if you are using multiple instances of SettingsProviders then you may get stale settings.
Note currently the settings provider only supports IConvertable types (http://msdn.microsoft.com/en-us/library/dsfy6sz9.aspx). If only supporting basic types is an issue, then maybe I will use json as storage.
Async Helpers
Execute.OnUIThread
Very simple usage, this is simply a static field which has a default implementation of dispatching a action to the UI Thread.
//Usage:
Execute.OnUIThread(()=> { /* will execute on UI Thread */ })
//To Unit Test:
Execute.OnUIThread = a=>a(); //Replace implementation so it simply executes on current thread
Execute.AsyncPattern & Execute.AsyncPatternWithResult
var stream = new MemoryStream();
var buffer = new byte[0];
const int offset = 0;
const int count = 0;
var bytesRead = Execute.AsyncPatternWithResult(stream.BeginRead, buffer, offset, count, stream.EndRead);
This is a pretty bad example, but you get the idea.
BackgroundWorker
backgroundWorker.DoWork()=>
{
var foo = Execute.AsyncPatternWithResult(webservice.BeginGetFoo, 123, webservice.EndGetFoo);
return Execute.AsyncPatternWithResult(webservice.BeginGetBar, foo, webservice.EndGetBar);
},
r=>
{
if (r.HadError)
throw e.Error;
UseBar(r.Result);
}
The use of Execute and Background worker aims to simplify certain scenarios quite easily, obviously don't use Execute.AsyncPattern on the UI Thread or anything silly like that :P
WindowsPhone.Abstractions
Same idea as System.Web.Abstractions, except for the phone. We currently provider two interfaces:
public interface IPhoneApplicationFrame : INavigate
{
Uri Source { get; set; }
JournalOwnership JournalOwnership { get; set; }
bool CanGoBack { get; }
bool CanGoForward { get; }
Uri CurrentSource { get; }
void StopLoading();
void GoBack();
void GoForward();
event NavigatedEventHandler Navigated;
event NavigatingCancelEventHandler Navigating;
event NavigationFailedEventHandler NavigationFailed;
event NavigationStoppedEventHandler NavigationStopped;
event FragmentNavigationEventHandler FragmentNavigation;
PageOrientation Orientation { get; }
event EventHandler<OrientationChangedEventArgs> OrientationChanged;
event EventHandler<ObscuredEventArgs> Obscured;
event EventHandler Unobscured;
}
and
public interface IPhoneApplicationService : IApplicationService
{
IdleDetectionMode UserIdleDetectionMode { get; set; }
IdleDetectionMode ApplicationIdleDetectionMode { get; set; }
IDictionary<string, object> State { get; }
StartupMode StartupMode { get; }
event EventHandler<LaunchingEventArgs> Launching;
event EventHandler<ActivatedEventArgs> Activated;
event EventHandler<DeactivatedEventArgs> Deactivated;
event EventHandler<ClosingEventArgs> Closing;
}
And in our testing project we have concrete implementation for use in unit tests so you can raise the events etc.
WP7 Essentials Testing
Doco coming soon
Diagnostics
Firstly we have a trace context, the provided implementation simply logs to Debug.Write..
public interface ITraceContext
{
///
/// <summary>
/// Writes trace information to the trace log.
/// </summary>
/// <param name="sourceType">The type of the object writing the trace message.</param>
/// <param name="messageCallback">A callback that builds the trace message to write to the log.</param>
void Write(Type sourceType, Func<string> messageCallback);
/// <summary>
/// Writes trace information to the trace log.
/// </summary>
/// <param name="sourceType">The type of the object writing the trace message.</param>
/// <param name="messageCallback">A callback that builds a series of trace messages to write to the log.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
void Write(Type sourceType, Func<IEnumerable<string>> messageCallback);
}
Secondly we have the MemoryUsage static class. It will only access DeviceExtendedProperties when the debugger is attached so your application does not have to worry about putting IDCAPIDENTITY_DEVICE into your manifest
Comments
amicimure
Hello :)