Windows Phone Essentials project information

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 { ///

/// Writes trace information to the trace log. /// /// The object writing the trace message. /// A callback that builds the trace message to write to the log. void Write(object source, Func 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 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
amicimure
03 Sep, 2011 09:28 AM

Hello :)

Your Comments

Used for your gravatar. Not required. Will not be public.
Posting code? Indent it by four spaces to make it look nice. Learn more about Markdown.

Preview