No default parameter values in Swift Protocols
Posted by davefielding76 in Uncategorized on November 7, 2014
According to Apple’s Swift Programming Language documentation (emphasis mine):
Protocols declare that conforming types must implement a method by including a protocol method declaration in the body of the protocol declaration. Protocol method declarations have the same form as function declarations, with two exceptions: They don’t include a function body, and you can’t provide any default parameter values as part of the function declaration
This means that it is not possible to use any default values for any functions defined in a protocol. The reason that I stumbled across this was because I was attempting to do the following in a SpriteKit project I have built in Swift:
protocol SomeTheme {
func animateSomething(completion: (() -> ()?)
}
class MyTheme {
func animateSomething(completion: (() -> ()? = nil) {
someNode.runAction(
SKAction.sequence([SKAction.waitForDuration(0.25, withRange: 0.25)]) {
if let comp = completion {
comp()
}
})
}
}
However, given its never actually possible to define the default value in the protocol, its impossible to take advantage of it in a calling method, unless the caller has explicit knowledge of the implementing class. So you cannot do this:
someThemeInstance.animateSomething()
you always have to explicitly include the completion, either as a parameter or closure:
someThemeInstance.animateSomething(nil)
// or
someThemeInstance.animateSomething() { }
Hopefully this is something that will be addressed in a future Swift update.
Problems using Swift + SpriteKit on iOS7 with XCode 6.1
Posted by davefielding76 in Uncategorized on November 7, 2014
I have been playing around with Apple’s new iOS development language, Swift, recently. Overall it seems a great language, but its clearly very early days and there are bugs in both the implementation and the development environment. Expect more posts on Swift in the coming weeks, but one of the most annoying issues I’ve found over the last few weeks has been this one:
There seems to be an issue with the way the XCode templates have changed between XCode 6.0 and 6.1 that causes problems when working with SpriteKit scenes in Swift.
The problem is with the initialization of the SKScene from the controller: XCode 6.1 generates some boilerplate code, which amongst other things, implements the ‘unarchiveFromFile’ extension method which doesn’t appear to work well with Swift on iOS7.1.
I got round this by using the following extension:
import UIKit
import SpriteKit
extension SKNode {
// The original method generated by XCode6.1 to initialise SpriteKit SKScenes
class func unarchiveFromFile<T: SKScene>(file : NSString) -> T {
let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks")
var sceneData = NSData(contentsOfFile: path!, options: .DataReadingMappedIfSafe, error: nil)
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData!)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as T
archiver.finishDecoding()
return scene
}
class func safeInit<T: SKScene>(size: CGSize, _ skFile: NSString) -> T {
let currentVersion = UIDevice.currentDevice().systemVersion
let isIOS8 = currentVersion.compare("8.0", options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
if isIOS8 {
let scene = T.unarchiveFromFile(skFile)
scene.size = size
return scene as T
} else {
return T(size: size)
}
}
}
And then calling this from your controller using the following code:
let skView = self.view as SKView let scene = GameScene.safeInit(skView.bounds.size, "GameScene") as GameScene
That seems to work for me. It feels like a bit of a hack but I can’t see any alternative option that actually works. As it happens, someone reported a very similar issue on StackOverflow recently, so this answer is also available on there.
I am working on the basis that this is probably a bug and will hopefully get fixed in a future release, at which point I will remove the hacky version checking.
Using Exception Helpers but avoiding CA1062 errors
Posted by davefielding76 in Uncategorized on November 2, 2012
I generally like to activate Code Analysis on projects that I’m working on, but this does add overhead in terms of the restrictions of what the analysis can cope with.
A perfect example of this is adhering to CA1062: Validate Arguments of public methods, especially when checking for null. A prime example would be:
public void MyMethod(string parameter1, object parameter2)
{
return string.Format(CultureInfo.InvariantCulture, parameter1, parameter2);
}
Now, if we were to run that past the code analysis engine, we would be on the receiving end of (at least) 2 violations for CA1062 and would then need to quadruple the codebase for this method:
public void MyMethod(string parameter1, object parameter2)
{
if (!string.IsNullOrEmpty(parameter1))
{
throw new ArgumentNullException("parameter1");
}
if (parameter2 == null)
{
throw new ArgumentNullException("parameter2");
}
return string.Format(CultureInfo.InvariantCulture, parameter1, parameter2);
}
Ugh. That’s a 10:1 ratio of validation code to actual work.
What would be much nicer would be to use an exception helper to allow us to do something like:
public void MyMethod(string parameter1, object parameter2)
{
Throw.IfNotNull(parameter1, "parameter1");
Throw.IfNotNull(parameter2, "parameter2");
return string.Format(CultureInfo.InvariantCulture, parameter1, parameter2);
}
By default, if we do this then the code analysis engine is unable to delve into the IfNotNull method to see what its doing and so cannot confirm whether we are validating the parameter.
However, it turns out we can let it know that its doing this by creating a ValidatedNotNullAttribute:
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class ValidatedNotNullAttribute : Attribute
{
}
then use this in the helper method:
public static class Throw
{
public void IfNotNull([ValidatedNotNull]object toCheck, string name)
{
if (ReferenceEquals(toCheck, null))
{
throw new ArgumentNullException(name);
}
}
}
And no more CA1062 warnings!
Stopping Visual Studio breaking on exceptions in a specific method
Posted by davefielding76 in Uncategorized on September 6, 2012
I have just discovered this nifty little trick to stop VS breaking on Exceptions in a specific method, irrespective of the settings under Debug -> Exceptions.
The DebuggerStepThrough attribute on a method does not just stop the debugger stepping into the method when you are hitting F11 on it, it will also not pick up thrown exceptions.
So, if you, like me, have an exception that may get thrown that you can’t do anything about (ie if a user cancels an operation inside a COM call that throws an E_ABORT COMException), this is one way to ignore it in the debugger.
Of course, you can’t have your cake and eat it, if you set this attribute then you also can’t step into and debug the method in question either, but with a little bit of refactoring you should be able to keep the offending method as short as possible.
Example:
[DebuggerStepThrough]
private void SendCrashLogs(string logFileName)
{
FileInfo logFile = new FileInfo(logFileName);
if (logFile.Exists)
{
List<dynamic> toRelease = new List<dynamic>();
dynamic outlookApplication = null;
Process[] existingOutlookProcess = Process.GetProcessesByName("Outlook");
bool alreadyRunning = existingOutlookProcess.Length > 0;
try
{
outlookApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Outlook.Application"));
toRelease.Add(outlookApplication);
// Create a new message and set the contents);
if (outlookApplication != null)
{
dynamic outlookMessage = outlookApplication.CreateItem(0);
toRelease.Add(outlookMessage);
if (outlookMessage != null)
{
// At the following line the user can cancel the operation
// which causes a COMException to be fired.
dynamic recipients = outlookMessage.Recipients;
toRelease.Add(recipients);
dynamic sender = recipients.Add(Environment.UserName);
toRelease.Add(sender);
foreach (string crashEmailRecipient in this.crashEmailRecipients)
{
recipients.Add(crashEmailRecipient);
}
foreach (dynamic recipient in recipients)
{
recipient.Resolve();
toRelease.Add(recipient);
}
outlookMessage.Subject = "Sending Logs";
string html = GenerateMessageBody();
outlookMessage.HTMLBody = html;
// Add the logs as an attachment
dynamic outlookMessageAttachments = outlookMessage.Attachments;
toRelease.Add(outlookMessageAttachments);
outlookMessageAttachments.Add(
logFileName, Type.Missing, outlookMessage.Body.Length + 1, logFileName);
outlookMessage.Send();
}
}
}
catch (COMException cEx)
{
if (cEx.Message.Contains("E_ABORT"))
{
this.log.Warn("User aborted sending of error logs via email");
}
else
{
this.log.Error("Could not send error logs via email", cEx);
}
}
catch (Exception ex)
{
this.log.Error("Could not send error logs via email", ex);
}
finally
{
// Need to quit the Outlook application if it wasn't already running
if (outlookApplication != null && !alreadyRunning)
{
outlookApplication.Quit();
}
toRelease.Where(i => i != null).ForEach(i => Marshal.FinalReleaseComObject(i));
toRelease.Clear();
}
}
}
An Outlook-style Desktop Alert Control in WPF part 2
Posted by davefielding76 in Controls on April 23, 2012
This is the 2nd part in the series. For the first part, see here.
In the first post, I considered the overall requirements & composition of the control and put together the code to display the first pass at an alert. Following on from this, we need to consider a few extra things:
- Adding pre-defined status images to the content area, alongside the text
- Styling the control to make it a bit more attractive (after all, there’s little use writing things in WPF if they are going to look functional at best
- Catering for more than 1 alert being visible at any one time
- The user should be able to close the alert before the timer fires
- Configurable actions to perform when the user clicks on the alert
One essential piece of information missing from the first part of the series is the ability to configure the length of time that each alert is displayed for. This is a simple addition to the DesktopAlertBase class:
/// <summary>The default Alert Duration</summary>
public static readonly TimeSpan DefaultAlertDuration = new TimeSpan(0, 0, 0, 5);
/// <summary>The dependency property for the duration of the alert</summary>
[SuppressMessage("Microsoft.StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Default Dependency Property setup")]
public static readonly DependencyProperty AlertDurationProperty =
DependencyProperty.Register("AlertDuration", typeof(TimeSpan), typeof(DesktopAlertBase));
/// <summary>Gets or sets the duration of the alert.</summary>
[Bindable(true)]
public TimeSpan AlertDuration
{
get { return (TimeSpan)this.GetValue(AlertDurationProperty); }
set { SetValue(AlertDurationProperty, value); }
}
// Add the following code to the constructor
this.AlertDuration = DefaultAlertDuration;
// Update the following method as follows:
/// <summary>
/// Called when the alert is loaded. Kicks off the time to hide the control after the requisite time
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.activeTimer = new DispatcherTimer { Interval = this.AlertDuration };
// Attach an anonymous method to the timer so that we can start fading out the alert when the timer is done.
this.activeTimer.Tick += delegate { Close(); };
this.activeTimer.Start();
}
Taking a step back, if we need to allow for multiple alerts to be visible at any one time, it seems sensible to have a singleton which controls the display of our alerts. This will restrict us slightly with regards to the flexibility of different types of alerts that we can use (as we’ll need calls for each one), but this can be refactored out at a later date.
So, lets create a new class, DesktopAlertService:
/// <summary>Service which is responsible for generating and positioning the Desktop Alerts</summary>
public class DesktopAlertService : IDesktopAlertService
{
#region Private Fields
/// <summary>Default alert height</summary>
private const int DefaultHeight = 80;
/// <summary>Default alert width</summary>
private const int DefaultWidth = 350;
/// <summary>The gap to keep between the bottom-most alert and the bottom of the screen</summary>
private const int BottomOffset = 15;
/// <summary>The gap to keep between the right-hand side of the alerts and the side of the screen</summary>
private const int SideOffset = 5;
/// <summary>The screen dimensions</summary>
private readonly Rect screenRectangle;
#endregion Private Fields
/// <summary>Initializes a new instance of the <see cref="DesktopAlertService"/> class.</summary>
public DesktopAlertService()
{
Rect rect = SystemParameters.WorkArea;
this.screenRectangle = new Rect(rect.X, rect.Y, rect.Width - SideOffset, rect.Height - BottomOffset);
this.DefaultProperties = new DesktopAlertProperties
{
AlertDuration = DesktopAlertBase.DefaultAlertDuration,
Width = DefaultWidth,
Height = DefaultHeight
};
}
/// <summary>Gets the settings.</summary>
public IDesktopAlertProperties DefaultProperties { get; private set; }
#region Public Methods
/// <summary>
/// Displays an alert with the given title and message
/// </summary>
/// <param name="title">The title.</param>
/// <param name="message">The message.</param>
public void DisplayAlert(string title, string message)
{
this.DisplayAlert(title, message, DesktopAlertImage.None);
}
/// <summary>
/// Displays an alert with the given category, title, message and image
/// </summary>
/// <param name="title">The title.</param>
/// <param name="message">The message.</param>
/// <param name="image">The image.</param>
public void DisplayAlert(string title, string message, DesktopAlertImage image)
{
this.DisplayAlert(new DesktopAlertProperties { Title = title, Message = message, Image = image });
}
/// <summary>
/// Displays the alert with the given properties
/// </summary>
/// <param name="properties">The properties for the alert.</param>
public void DisplayAlert(IDesktopAlertProperties properties)
{
if (!Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.Invoke(
new Action<IDesktopAlertProperties>(this.DisplayAlert), properties);
return;
}
// Figure out where to place the window based on the current screen resolution
SimpleAlert alert = new SimpleAlert
{
Title = properties.Title,
Message = properties.Message,
Width = properties.Width ?? this.DefaultProperties.Width ?? DefaultWidth,
Height = properties.Height ?? this.DefaultProperties.Height ?? DefaultHeight,
AlertDuration =
properties.AlertDuration
?? this.DefaultProperties.AlertDuration ?? DesktopAlertBase.DefaultAlertDuration
};
alert.Left = this.screenRectangle.Right - alert.Width - alert.BorderThickness.Right;
alert.Top = this.screenRectangle.Bottom - (alert.Height + alert.BorderThickness.Bottom);
if (properties.Image != DesktopAlertImage.None)
{
alert.Image = this.GetImage(properties.Image);
}
alert.Closed += this.OnClosed;
}
#endregion Public Methods
#region Private Methods
/// <summary>
/// Handles the Closed event of the alert control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnClosed(object sender, EventArgs e)
{
DesktopAlertBase alert = sender as DesktopAlertBase;
if (alert != null)
{
alert.Closed -= this.OnClosed;
}
}
#endregion Private Methods
}
I have left the GetImage() method out for now – this can be viewed in the full source code which will be posted alongside the final part of this series.
I have also defined a new interface, IDesktopAlertProperties which determines what is displayed as part of the alert:
/// <summary>A collection of properties for a single Desktop Alert </summary>
public interface IDesktopAlertProperties
{
/// <summary>Gets or sets the title.</summary>
string Title { get; set; }
/// <summary>Gets or sets the message.</summary>
string Message { get; set; }
/// <summary>Gets or sets the image.</summary>
DesktopAlertImage Image { get; set; }
/// <summary>Gets or sets the duration of the alert.</summary>
TimeSpan? AlertDuration { get; set; }
/// <summary>Gets or sets the width.</summary>
int? Width { get; set; }
/// <summary>Gets or sets the height.</summary>
int? Height { get; set; }
}
Again, we have the DesktopAlertImage, which is an enum, specified here. This is just a list of available images.
Our application entry point now looks like this:
public partial class MainWindow : Window
{
/// <summary>The desktop service</summary>
private readonly DesktopAlertService service = new DesktopAlertService();
public MainWindow()
{
InitializeComponent();
this.service.DisplayAlert(
"Simple Alert",
"This is the text for the simple alert popup, which should wrap if too long to display on a single line");
}
}
By adding this service to our implementation, the call is simplified for our users. This can easily be converted to a singleton or extended to allow multiple alert types. However, by keeping our properties on the controls as Dependency Properties, it is still possible to use them in the more tradition* WPF way.
* – if there is such a thing.
The next parts in this series will cover the styling, images, triggers (ie mouse-over) and additional functionality.
Full source code will be posted alongside the final part.
WPF ResourceDictionary Precedence
Posted by davefielding76 in Controls on March 7, 2012
There doesn’t seem to be a huge amount of information available on the precedence of ResourceDictionary entries in XAML. Knowing which styles will be used when you have more than one dictionary containing styles with the same name is clearly necessary.
According to the official MSDN documentation:
Resources in a merged dictionary occupy a location in the resource lookup scope that is just after the scope of the main resource dictionary they are merged into. Although a resource key must be unique within any individual dictionary, a key can exist multiple times in a set of merged dictionaries. In this case, the resource that is returned will come from the last dictionary found sequentially in the MergedDictionaries collection. If the MergedDictionaries collection was defined in XAML, then the order of the merged dictionaries in the collection is the order of the elements as provided in the markup. If a key is defined in the primary dictionary and also in a dictionary that was merged, then the resource that is returned will come from the primary dictionary. These scoping rules apply equally for both static resource references and dynamic resource references.
This can come in handy if you need to override styles from a 3rd party Resource Dictionary within your own – provided your dictionary is referenced after the original, everything works nicely.
Using UAC to request Administrative Privileges from c#
Posted by davefielding76 in Uncategorized on February 27, 2012
With the advent of Windows Vista and Windows 7, we need to consider access rights more than ever. Previously, applications running on windows-based operating systems up to and including XP could just rely on having wide access to perform almost any task. Although many corporate systems are more locked down, the software running on them is generally heavily tailored to do so.
With Windows Vista/7, this locked down approach is brought to the consumer versions of the operating system – by default users do not get administrative privileges – to get these privileges the OS will request confirmation from the user that they are happy for the application to be run in the elevated context. There are 2 main ways of causing the OS to display the prompts:
- Creating / updating the application manifest file to include
- Launching the application setting the “runas” verb from code
As this blog is centered around c#, lets take a look at the latter.
Once the application is launched, there is no way to elevate the privileges from code. We must therefore look at making sure it is started correctly. Adding the following code to the program start does just this:
WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool hasAdministrativeRight = pricipal.IsInRole(WindowsBuiltInRole.Administrator);
if (!hasAdministrativeRight)
{
// relaunch the application with admin rights
string fileName = Assembly.GetExecutingAssembly().Location;
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = fileName;
try
{
Process.Start(processInfo);
}
catch (Win32Exception)
{
// This will be thrown if the user cancels the prompt
}
return;
}
As you can see, what we are actually doing is re-launching the app, setting the ProcessStartInfo.Verb property to “runas”. This automatically causes the OS to prompt the user for admin access.
This can cause a few problems debugging – the easiest way round is to ensure the Visual Studio process is run as an administrator, otherwise we will just launch a new instance of the application whenever we attempt to debug.
An Outlook-style Desktop Alert control in WPF (part 1)
Posted by davefielding76 in Controls on January 22, 2012
One frequently useful way of notifying users of information for an application is via some sort of transient popup, similar to the Microsoft Outlook Desktop Alert. There are a variety of paid-for controls out there which contain similar functionality, but I decided to build one in WPF.
Requirements
Before we start, its always best to work out exactly what we need the alerts to do.
- Display an alert, on demand which contains, as a minimum a title and some content
- The alert should automatically appear in the correct location – just inside the Windows system tray, irrespective of the location.
- The alert should have a configurable opacity
- The alert should stay visible for a configurable period of time, then disappear automatically
- Multiple alerts can be displayed at the same time without overlapping (within reason – where there are more alerts than screen real-estate, they can overlap as necessary).
- When the mouse cursor hovers over the alert, it should, as a minimum have an opacity of 1 to be fully visible and should not disappear
- When the mouse moves away from the alert, the opacity should return to the configured value and any timing related to the alert disappearing should restart
- The title can be set
- The content can be configured and should as a minimum be some text and an icon
- Users can close the alert prior to the planned close.
- A configurable action can be fired when the user clicks on an alert, configurable per alert.
- <<CONTEXT>> some way of giving context and setting options, etc.
NOTE: One of my original requirements for this alert was that it should fade-in and fade-out in the same way that the default Outlook one does. However, after doing some testing on this (and comparing it to other solutions), it appears that there are frequent OutOfMemoryExceptions thrown. Removing the fading resolves the problem, so I have removed the requirement for now until I can find a way round this.
Designing the Alert
It makes sense to keep the content of the alert as flexible as possible. However, all alerts will we require a title area, a close button and the content area. The obvious layout is shown here.
To emphasise the title it will be shown in bold. The close button is at the far right of the title area. Taking up the rest of the control is the content area, which will be configurable.
Configuring the Content
Whilst keeping the content configurable to allow many different types of alert, for the purposes of this post I will concentrate on using a simple alert with an icon and message text. The icon will be displayed to the left of the content area (with a fixed size), with the text taking up the rest.
To build this up in WPF, it makes sense to split the control into 2 parts:
- A Custom Control containing the basic layout: title area, close box & content area
- A User Control inheriting this which has the content (icon & message).
In this way, we can just use a different User Control to display different content, keeping the same behaviour of the overall alert.
DesktopAlertBase
Add a new Custom Control to the project called DesktopAlertBase. Enter the following xaml into the Themes\Generic.xaml file:
<Style TargetType="{x:Type DesktopAlert:DesktopAlertBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DesktopAlert:DesktopAlertBase}">
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Margin="5, 0, 0, 0"
FontWeight="Bold"
FontSize="12"
Opacity="1.0"
Text="{TemplateBinding Title}"/>
<Button Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Width="15"
Height="15"
Foreground="Red">x</Button>
</Grid>
</Grid>
<ContentControl Grid.Row="1" Content="{TemplateBinding Content}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Update the new custom control as follows:
/// <summary>Desktop alert class</summary>
public abstract class DesktopAlertBase : Window
{
/// <summary>Initializes a new instance of the <see cref="DesktopAlertBase"/> class.</summary>
public DesktopAlertBase()
{
Visibility = Visibility.Visible;
// Set some default properties for the alerts.
// These can be changed by the derived alerts.
this.ShowInTaskbar = false;
WindowStyle = WindowStyle.None;
ResizeMode = ResizeMode.NoResize;
Topmost = true;
AllowsTransparency = true;
Opacity = 0.9;
BorderThickness = new Thickness(1);
BorderBrush = Brushes.Black;
Background = Brushes.White;
}
/// <summary>Initializes static members of the <see cref="DesktopAlertBase"/> class.</summary>
static DesktopAlertBase()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof (DesktopAlertBase), new FrameworkPropertyMetadata(typeof (DesktopAlertBase)));
}
}
This will give us a new control, but without hooking up either the timer or the close button to close the window. To do this:
- Amend the close button in the template and give it a name: “PART_CloseButton”
- Add “Loaded += this.OnLoaded;” to the constructor.
- Add the line Loaded += this.OnLoaded; to the constructor
- Add the following code:
/// <summary>The timer that determines the length of time that the control is visible for</summary>
private DispatcherTimer activeTimer;
/// <summary>Hook up the button click handlers, etc</summary>
public override void OnApplyTemplate()
{
ButtonBase closeButton = Template.FindName("PART_CloseButton", this) as ButtonBase;
if (closeButton != null)
{
closeButton.Click += this.OnCloseButtonClick;
}
}
/// <summary>
/// If the user clicks the close button, stop the timer that counts how long the alert and simply close it
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
private void OnCloseButtonClick(object sender, RoutedEventArgs e)
{
this.activeTimer.Stop();
Close();
}
/// <summary>
/// Called when the alert is loaded. Kicks off the time to hide the control after the requisite time
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
private void OnLoaded(object sender, RoutedEventArgs e)
{
this.activeTimer = new DispatcherTimer { Interval = TimeSpan.Parse("0:0:05") };
// Attach an anonymous method to the timer so that we can start fading out the alert when the timer is done.
this.activeTimer.Tick += delegate { Close(); };
this.activeTimer.Start();
}
Text Alerts
Now we have the basis of the alert, we can create a new User Control to implement a simple text style alert. To do this, add a new User Control called SimpleControl. Add the following code for the xaml & c#:
/// <summary>
/// Interaction logic for SimpleAlert.xaml
/// </summary>
public partial class SimpleAlert
{
public static DependencyProperty MessageProperty = DependencyProperty.Register(
"Message",
typeof(string),
typeof(SimpleAlert));
public static DependencyProperty ImageProperty = DependencyProperty.Register(
"Image",
typeof(ImageSource),
typeof(SimpleAlert));
[Bindable(true)]
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
[Bindable(true)]
public ImageSource Image
{
get { return (ImageSource) GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public SimpleAlert()
{
InitializeComponent();
}
}
<!-- XAML for the user control content -->
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Image}"/>
<TextBlock FontSize="12"
Padding="5"
TextWrapping="Wrap"
Grid.Column="1"
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Message}"/>
</Grid>
You will also need to change the XAML definition from a UserControl to a DesktopAlertBase. Now we have this, we can create the alert from the MainWindow.cs and position it in the relevant place on the screen:
public partial class MainWindow : Window
{
private SimpleAlert alert;
public MainWindow()
{
InitializeComponent();
alert = new SimpleAlert
{
Title = "Simple Alert",
Message =
"This is the text for the simple alert popup, which should wrap if too long to display on a single line",
Width = 300,
Height = 75,
};
alert.Left = SystemParameters.WorkArea.Right - alert.Width - alert.BorderThickness.Right;
alert.Top = SystemParameters.WorkArea.Bottom - (alert.Height + alert.BorderThickness.Bottom);
}
}
And there we have it – the first desktop alert. In the next posts on the subject I will go into more detail on the images, styling of the control, positioning, displaying multiple alerts simultaneously and user interactions & effects (ie mouseover, context menus, etc).
An IDisposable Locking implementation
Posted by davefielding76 in Uncategorized on June 29, 2011
c# provides a very easy mechanism for simple thread safety and synchronisation: the lock statement. However, in many cases, a simple lock is too restrictive as it will block all other access o the locked object, irrespective of the operation being performed.
For more fine-grained control, there are a few options, but since .net3.5, my personal preference has always been to use the ReaderWriterLockSlim (see here for more information). This has the following advantages:
- We can have multiple concurrent threads reading
- Only 1 thread can perform write operations – this will wait for all currently executing readers to complete before blocking others and executing itself.
- When explicitly required, we can upgrade a Read operation to a Write operation
- We can choose whether to allow lock recursion or not
However, one of the nice advantages of the lock statement is the syntactic sugar added within the language spec which means we can do something like:
lock(myLockObject)
{
// access my x-thread data
}
I don’t think anyone would disagree that this is a nice and neat way of writing a thread synchronization block. Unfortunately, to implement a ReaderWriterLockSlim (or any of the other locking mechanisms apart from the lock statement), we have no such options, leading to much bulkier code.
this.dataLock.EnterReadLock();
try
{
// access my x-thread data
}
finally
{
this.dataLock.ExitReadLock();
}
One way round this is to create a Disposable object which Enters the locks required and Exits them on calls to IDispose.
/// <summary>Type of lock operation</summary>
public enum LockType
{
/// <summary>A read lock, allowing multiple simultaneous reads</summary>
Read,
/// <summary>An upgradeable read, allowing multiple simultaneous reads, but with the potential that ths may be upgraded to a Write lock </summary>
UpgradeableRead,
/// <summary>A blocking Write lock</summary>
Write
}
/// <summary>Wrapper for the ReaderWriterLockSlim which allows callers to dispose the object to remove the lock </summary>
public class DisposableLockWrapper : IDisposable
{
/// <summary>The lock object being wrapped</summary>
private readonly ReaderWriterLockSlim readerWriterLock;
/// <summary>The lock type</summary>
private readonly LockType lockType;
/// <summary>
/// Initializes a new instance of the <see cref="DisposableLockWrapper"/> class.
/// </summary>
/// <param name="readerWriterLock">The reader writer lock.</param>
/// <param name="lockType">Type of the lock.</param>
public DisposableLockWrapper(ReaderWriterLockSlim readerWriterLock, LockType lockType)
{
this.readerWriterLock = readerWriterLock;
this.lockType = lockType;
switch (this.lockType)
{
case LockType.Read:
this.readerWriterLock.EnterReadLock();
break;
case LockType.UpgradeableRead:
this.readerWriterLock.EnterUpgradeableReadLock();
break;
case LockType.Write:
this.readerWriterLock.EnterWriteLock();
break;
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed objects
switch (this.lockType)
{
case LockType.Read:
this.readerWriterLock.ExitReadLock();
break;
case LockType.UpgradeableRead:
this.readerWriterLock.ExitUpgradeableReadLock();
break;
case LockType.Write:
this.readerWriterLock.ExitWriteLock();
break;
}
}
}
}
To keep the implementation details away from the callers, I decided to implement a set of Extension methods to the ReaderWriterLockSlim class:
/// <summary>Extension methods for the ReaderWriterLockSlim object </summary>
public static class ReaderWriterLockSlimExtension
{
/// <summary>
/// Obtains a Read lock on the ReaderWriterLockSlim object
/// </summary>
/// <param name="readerWriterLock">The reader writer lock.</param>
/// <returns>An IDisposable object that will release the lock on disposal</returns>
public static IDisposable ObtainReadLock(this ReaderWriterLockSlim readerWriterLock)
{
return new DisposableLockWrapper(readerWriterLock, LockType.Read);
}
/// <summary>
/// Obtains an Upgradeable Read lock on the ReaderWriterLockSlim object
/// </summary>
/// <param name="readerWriterLock">The reader writer lock.</param>
/// <returns>An IDisposable object that will release the lock on disposal</returns>
public static IDisposable ObtainUpgradeableReadLock(this ReaderWriterLockSlim readerWriterLock)
{
return new DisposableLockWrapper(readerWriterLock, LockType.UpgradeableRead);
}
/// <summary>
/// Obtains a Write Lock on the ReaderWriterLockSlim object
/// </summary>
/// <param name="readerWriterLock">The reader writer lock.</param>
/// <returns>An IDisposable object that will release the lock on disposal</returns>
public static IDisposable ObtainWriteLock(this ReaderWriterLockSlim readerWriterLock)
{
return new DisposableLockWrapper(readerWriterLock, LockType.Write);
}
}
We can now use the ReaderWriterLockSlim nice an easily by calling as follows:
using (this.dataLock.ObtainReadLock())
{
// access my x-thread data
}
Reflection with Generic Methods
Posted by davefielding76 in Uncategorized on June 14, 2011
Two of the really powerful features of .net to me are Generics and Reflection. However, there seems to be very little documentation around indicating how you use them together.
For example, consider the following class:
public class MyNonGenericClass
{
void NormalMethod(object normalParameter)
{
Console.WriteLine(normalParameter);
}
void GenericMethod<T>(T genericParameter)
{
Console.WriteLine(genericParameter);
}
}
The first method is easy to execute using reflection:
public void CallNormalMethod()
{
MethodInfo method = typeof(MyNonGenericClass).GetMethod("NormalMethod");
method.Invoke(new MyNonGenericClass(), new object[] { "normal method" });
}
Until investigating recently, I was unsure how one would go about executing the second. It turns out that its also very easy:
public void CallGenericMethod()
{
// Use the reflection equivalent of "new MyNonGenericClass().GenericMethod<string>("...")"
MethodInfo method = typeof(MyNonGenericClass).GetMethod("GenericMethod");
MethodInfo genericMethod = method.MakeGenericMethod(new[] { typeof(string) });
genericMethod.Invoke(new MyNonGenericClass(), new object[] { "generic method" });
}
