Friday, December 24, 2010

Balloon Pop-ups and Toaster Pops

Recently I was looking into balloons, toaster-pops, and general system tray messages.  There's nothing much WPF gives you out of the box to give you a leg up. So I turned to Google to search for either code samples or control libraries.  I found a fantastic free open-source all-in-one framework for all things balloons, system-tray and toaster-pops.

Check it out here:
http://www.hardcodet.net/projects/wpf-notifyicon



So it looks cool, but how hard is it to make a quick and dirty sample application that shows a custom balloon pop-up out of the system tray? (and yes it follows the tray if you move your task bar).


  1. Create a new WPF project and reference the one Hardcodet.Wpf.TaskbarNotification DLL.
  2. Add this code to the MainWindow.Xaml
    <TextBlock Text="Wait 5 seconds for the ring balloon popup to appear." />
    <tb:TaskbarIcon x:Name="tb" VerticalAlignment="Top" Visibility="Hidden" />
    
    
  3. Add this to the code behind:
    private DispatcherTimer timer;
    
            public MainWindow()
            {
                InitializeComponent();
                Loaded += OnLoaded;
            }
    
            private void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
            {
                this.timer = new DispatcherTimer(new TimeSpan(0, 0, 6), DispatcherPriority.Normal, OnTimerTick, Dispatcher);
                this.timer.Start();
            }
    
            private void OnTimerTick(object sender, EventArgs e)
            {
                var balloon = new FancyBalloon { BalloonText = "Ring Ring" };
                tb.ShowCustomBalloon(balloon, PopupAnimation.Scroll, 3000);
            }
  4. Add a user control to define what you want your custom pop-up to look like.
    <UserControl x:Class="WpfBasicBalloon.FancyBalloon"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 Height="300" Width="300">
        <Grid>
            <Border 
                Opacity="0.5"
                Background="Pink" 
                BorderBrush="Red"
                BorderThickness="2"
                CornerRadius="10"
                Margin="10">
                <Border.BitmapEffect>
                    <DropShadowBitmapEffect />
                </Border.BitmapEffect>
                <StackPanel Margin="10">
                <TextBlock Text="Hello World - in pink just for Jo. :-)" />
                <TextBlock Text="{Binding BalloonText}" />
            </StackPanel>
            </Border>
        </Grid>
    </UserControl>

Easy.


Its so little code, given a few days of my cat walking randomly across my keyboard, there's a good chance he will come up with this code on his own. Better chances of winning the lottery over the holiday break any way!

Happy holidays.

Wednesday, December 22, 2010

Extracting A ControlTemplate From An Existing WPF Control

There are a number of tools to do this, not least of which is Blend.  But sometimes you need some code to do it for you.  There have been a few instances where Blend was unable to extract the control template, and resorting to code is the last line of defense.

Here's a snippet of code from a test application where Group1 is an element (of type RibbonGroup).  This code comes from a code behind from a xaml window.

var template = this.Group1.Template;
            var xmlSettings = new XmlWriterSettings { Indent = true };

            var builder = new StringBuilder();
            XmlWriter writer = XmlWriter.Create(builder, xmlSettings);
            XamlWriter.Save(template, writer);
            Clipboard.SetText(builder.ToString());
            Debug.WriteLine(builder.ToString());
This will output the control template xaml to the Debug output and also copy it to the clipboard.

Tuesday, December 21, 2010

Grrrr TFS Crashed Build Locked Files

Today I had to fix a build issue, which are few and far between these days with TFS 2010.  By and large I love it, it has a huge array of features and advancements over previous version. And sure beats the hell out of Subversion for features and ease of use.

The build crashed after someone managed to checked in the wrong version of / or corrupt DLLs. The result was files locked by the build machine that could not be rolled back or checked out.

When I attempted to check out the files to roll them back obviously being locked I got the error message below..."is locked for check-out by..."
This problem cannot be solved by using the IDE. Only the command line can fix this.  The good news is its totally doable and the above error gives you the workspace name you need.

Jump into a Visual Studio 2010 Command Prompt window and type the following:

TF undo /workspace:<WorkspaceNameGivenInOutput> "<FullPathToFileToUndo>" /collection:<FullHttpUrlIncludingPortNumberAndCollectionProjectName>

Thursday, December 16, 2010

Exception Template

Here's an Exception template that complies with all Code Analysis warnings and best practices:
Writing a custom exception couldn't be more straight forward.  However there are some things that are not obvious that can be useful to comply with.

The choice to write a custom exception usually follows the process of checking to see if an existing .NET framework exception adequately explains the issue with enough information.  DO NOT throw System.Exception or System.SystemException, that just reeks of rotten lazy coding.

If you're using the "All Rules" Code Analysis category in your project you'll be walked through a series of changes to comply.  These all make sense when you think about them. I'll walk through them below.  For the sake of expediency here's a template for a standard custom exception to save you the trouble of trying several times to resolve all warnings:


namespace MyNamespace
{
    using System;
    using System.Runtime.Serialization;

    /// <summary>
    /// A Custom exception ...
    /// </summary>
    [Serializable]
    public class CustomException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        public CustomException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="message">The message.</param>
        public CustomException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="innerException">The inner exception.</param>
        public CustomException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CustomException"/> class.        
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
        protected CustomException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
 

        /*
         * Use this when adding custom properties to an exception.
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("CustomProperty", CustomProperty);
        }
        */
        }
}


[Serializable]
This is good practice to allow exceptions to be saved in full when persisted, or sent over a communications channel. Although WCF requires that all top level exceptions be FaultExceptions, I believe you can use a serializable exception as an inner exception. Also consider implementing ISerializable.

Inherit from Exception.
There is no real benefit from having deep inheritance hierarchies of exceptions, and this is the recommendation of the Microsoft Framework Design Guidelines.  A good example of excellent use of Exception inheritance with good meaning are the System.IO.IOException types. This allows you to catch all IO related exceptions. Also the name should always be suffixed with "Exception" for clarity and consistency with other .NET framework exceptions.  Its better to have many specific custom exception types than a few overused types that dilute their meaning.  One last thing on this, don't bother deriving from ApplicationException, to quote Jeffrey Richter: "its a class that should not be part of the .NET framework. The original idea was that classes derived from SystemException would indicate CLR exceptions where non-CLR would derive from ApplicationException. However a lot of exception classes didn't follow this guideline...and it lost all meaning." Do not derive from any other exception other than Exception or SystemException (for more information see the Framework Design Guidelines chapter on exceptions).

Constructors.
Because constructors cannot be prescribed in a base-class the three exception constructors that are always expected to be present are the three shown above.  Your custom exception can be passed into .NET framework code and into other code that is consistent with the .NET framework. For this reason you should always have these three constructors available.

The last constructor is to ensure serialization is performed correctly. 

Don't go nuts on overloaded constructors rather prefer properties. 

Don't bother with error codes of any kind, this is what Exception types are for.

Another thing worth considering is using the System.Environment.FailFast method to ensure your process terminates quickly and as cleanly as possible.  In a no-win situation this is the best idea when there is an unhandled exception that leaves the application in an inconsistent state.

Don't be tempted to use custom exception types in "normal" program logic. Ie: catching a FileNotFoundException and then creating a file.  This will result in bad performing code.  Rather check and create (ie File.Exists method).

When making extensive use of logging, don't be caught out by thinking that logging means you don't need exceptions.  When writing reusable frameworks and toolkits, you cannot assume how someone will want to use your library. Log by all means, but throw an exception that the consumer can optionally catch and have the choice of attempting a recovery or failing the process.

Monday, December 13, 2010

Microsoft WPF 2010 Ribbon

I've been looking into implementing a ribbon control, and found that Microsoft have released the source for there 2010 ribbon! (The 2010 Ribbon is also known as a "Scenic" Ribbon style). Great stuff, thanks Microsoft!

Check out these links for more information:

Microsoft also have a page describing what the different components of the ribbon are and when it should be used: Ribbon WPF and also some common application UI patterns and usage recommendations.

There is full support for the MVVM pattern in the ribbon and support for ICommand.

Screenshots:

Here's one I have started to customise to push the ribbon to the right to make space for companion panel I want to sit next to the ribbon.



I've also started reviewing the Fluent Ribbon. See these links:
Looking at it from a code difficulty point of view and amount of code required, Fluent is definitely easier and you write about 30% less code than what is required for the Microsoft WPF Ribbon.  However, the Microsoft offering seems to be faster, and has better support for MVVM.

I am also looking into Infragistics .NetAdvantage 2010 Volume 3, which includes (as of October 2010 I believe) a "Scenic" Office 2010 style Ribbon Bar.  It also has a cool feature called ColorWash which allows a measure of control over the color scheme of the bar.

It looks pretty cool on the surface but it doesn't give you exact control over the resulting color.  Which I found quite annoying.  I found it far too hard to restyle this to be a black scheme.  Infragistics have only given one simple Office 2010 style, the blue "Scenic" style. Seems like the Henry Ford approach, "...you can have any color as long as its black...".  Finally the overall style does not seem to match closely the Office 2010 style, it seems a little over simplified.

The above example has set the Wash Color to Black. But this is still no where near dark enough, and doesn't give me the control I want. For example changing the background to a different gradient fill. You can also see the style is subtly simpler than the Fluent and Microsoft images above.

My verdict?  In my humble opinion Infragistics comes in at third on this one.  It feels like they have retro fitted 2010 styling rather than considering all the features in the Office 2010 Ribbon.  Fluent is very good and seems easy to use but there are a few tiny things missing in comparison to Microsoft.  However, if ease of implementation is what you're after Fluent looks like the way to go. Me personally, I need all the features Microsoft has over Fluent (Keyboard Navigation, full control of Backstage, and mini-toolbar and shortcut tool-bar).

Sunday, December 12, 2010

Global Hotkeys and User Activity Detection

Back in July I posted about a job where I have to be able to detect user input (or absence of it) through keyboard or mouse.  In addition, how do you go about setting up global OS level hot keys?

Detecting Keyboard and Mouse Input
The main ingredient is the Win32 function

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(
        int idHook,
        LowLevelInputProc lpfn,
        IntPtr hMod,
        uint dwThreadId);

This function is used to hook into many Windows events.  The first parameter is the type of hook you would like to "hook" into. The term hook is used basically to describe subscribing to a Windows event.
The second parameter Lpfn is the callback delegate Windows should invoke when an event occurs. The third is your application's module handle, and finally the last is the thread id in your application Windows should use to invoke the callback.

To set the hook, is reasonably straight forward. I've written a wrapper method to simplify the invocation of the Win32 call:


private static IntPtr SetHook(LowLevelInputProc proc, int hookTypeConstant)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            {
                using (ProcessModule curModule = curProcess.MainModule)
                {
                    if (curModule == null)
                    {
                        return IntPtr.Zero;
                    }

                    return SetWindowsHookEx(
                        hookTypeConstant,
                        proc,
                        GetModuleHandle(curModule.ModuleName),
                        0);
                }
            }
        }

The two hook types I am interested in are Keyboard keypress events (int WH_KEYBOARD_LL = 13) and Mouse keypress events (int WH_MOUSE_LL = 14).  The callback has the signature:


private delegate IntPtr LowLevelInputProc(int nCode, IntPtr wParam, IntPtr lParam);

The three parameters are then used to give you information about the event and vary between different hook types.

My end goal is to be able to wrap these two hooks into a reusable class. The idea is to make a static class that has standard .NET events that are easier to subscribe to and deal with.


namespace KeyboardHookConsole
{
    using System;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    public static class InputDeviceInterceptor
    {
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Maps to Win32.")]
        private const int WH_KEYBOARD_LL = 13;

        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Win32.")]
        private const int WH_MOUSE_LL = 14;

        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Maps to Win32.")]
        private const int WM_KEYDOWN = 0x0100;

        private static IntPtr keyboardHookId = IntPtr.Zero;

        private static IntPtr mouseHookId = IntPtr.Zero;

        private delegate IntPtr LowLevelInputProc(int nCode, IntPtr wParam, IntPtr lParam);

        private static readonly LowLevelInputProc KeyboardCallback = KeyboardHookCallback;

        private static readonly LowLevelInputProc MouseCallback = MouseHookCallback;

        public static event EventHandler<InterceptedKeyEventArgs> KeyboardInput;

        public static event EventHandler<InterceptedMouseEventArgs> MouseInput;

        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }

        public static void SetHook()
        {
            keyboardHookId = SetHook(KeyboardCallback, WH_KEYBOARD_LL);
            mouseHookId = SetHook(MouseCallback, WH_MOUSE_LL);
        }

        public static void Unhook()
        {
            UnhookWindowsHookEx(keyboardHookId);
            UnhookWindowsHookEx(mouseHookId);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(
            IntPtr hhk,
            int nCode,
            IntPtr wParam,
            IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        private static IntPtr KeyboardHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int code = Marshal.ReadInt32(lParam);
                var handler = KeyboardInput;
                if (handler != null)
                {
                    handler(null, new InterceptedKeyEventArgs((Keys)code));
                    //// handler(null, new InterceptedKeyEventArgs());
                }
            }

            return CallNextHookEx(keyboardHookId, nCode, wParam, lParam);
        }

        private static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // MouseButtonState left = MouseButtonState.Released, right = MouseButtonState.Released;
            // var point = new Point();

            bool raiseEvent = false;
            // var hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));

            if (nCode >= 0)
            {
                if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
                {
                    // left = MouseButtonState.Pressed;
                    raiseEvent = true;
                }

                if (MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
                {
                    // right = MouseButtonState.Pressed;
                    raiseEvent = true;
                }

                if (MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
                {
                    raiseEvent = true;
                    // point.X = hookStruct.pt.x;
                    // point.Y = hookStruct.pt.y;
                }

                if (raiseEvent)
                {
                    var handler = MouseInput;
                    if (handler != null)
                    {
                        // handler(null, new InterceptedMouseEventArgs(left, right, point));
                        handler(null, new InterceptedMouseEventArgs());
                    }
                }
            }

            return CallNextHookEx(mouseHookId, nCode, wParam, lParam);
        }

        private static IntPtr SetHook(LowLevelInputProc proc, int hookTypeConstant)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            {
                using (ProcessModule curModule = curProcess.MainModule)
                {
                    if (curModule == null)
                    {
                        return IntPtr.Zero;
                    }

                    return SetWindowsHookEx(
                        hookTypeConstant,
                        proc,
                        GetModuleHandle(curModule.ModuleName),
                        0);
                }
            }
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(
            int idHook,
            LowLevelInputProc lpfn,
            IntPtr hMod,
            uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }
        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }
    }
}

Here's a sample console application that tests this class.

namespace ConsoleApplication1
{
    using System;
    using System.Windows.Forms;
    using KeyboardHookConsole;

    public static class Program
    {
        public static void Main()
        {
            InputDeviceInterceptor.SetHook();
            InputDeviceInterceptor.KeyboardInput += (s, e) => Console.WriteLine(e.Key.ToString());

            InputDeviceInterceptor.MouseInput += (s, e) => Console.WriteLine("Mouse moved");

            Application.Run();

            InputDeviceInterceptor.Unhook();
        }
    }
}



Finally more close to my ultimate end goal, here's a WPF application with a check box to indicate if the user has recently typed input, or moved their mouse:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Are you present?" />
            <CheckBox IsChecked="{Binding Present}" />
        </StackPanel>
    </StackPanel>
</Window>

namespace WpfApplication1
{
    using System;
    using System.ComponentModel;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Threading;
    using KeyboardHookConsole;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : INotifyPropertyChanged
    {
        private readonly DispatcherTimer awayTimer = new DispatcherTimer();
        private bool present;

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Loaded += OnLoaded;
            Closing += OnClosing;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public bool Present
        {
            get
            {
                return this.present;
            }

            set 
            { 
                if (value)
                {
                    this.awayTimer.Start();
                }

                this.present = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Present"));
            }
        }

        private void OnAwayTimerTick(object sender, EventArgs e)
        {
            Present = false;
            this.awayTimer.Stop();
        }

        private void OnClosing(object sender, CancelEventArgs e)
        {
            InputDeviceInterceptor.KeyboardInput -= OnInterceptorKeyboardInput;
            InputDeviceInterceptor.MouseInput -= OnInterceptorMouseInput;
            InputDeviceInterceptor.Unhook();
        }

        private void OnInterceptorKeyboardInput(object sender, InterceptedKeyEventArgs e)
        {
            // Toggle the user presence property
            Task.Factory.StartNew(() =>
                                  {
                                      if (!Present)
                                      {
                                          Dispatcher.BeginInvoke(new Action(() => Present = true));
                                      }
                                  });
        }

        private void OnInterceptorMouseInput(object sender, InterceptedMouseEventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                if (!Present)
                {
                    Dispatcher.BeginInvoke(new Action(() => Present = true));
                }
            });
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            InputDeviceInterceptor.SetHook();
            InputDeviceInterceptor.KeyboardInput += OnInterceptorKeyboardInput;
            InputDeviceInterceptor.MouseInput += OnInterceptorMouseInput;
            this.awayTimer.Interval = new TimeSpan(0, 0, 5);
            this.awayTimer.Tick += OnAwayTimerTick;
            this.awayTimer.Start();
        }
    }
}

Setting Hot Keys will follow.

Monday, November 29, 2010

Casting Enums

I had to think hard today on how to cast back to an Enum from an int using Reflection, so seems like a good topic to recap on. If you know what you want to cast it to thats easy, just cast it, but what if you have an instance of Type and you want to cast it to that type?

I think everyone knows that enums are based on integers (32 bit or 64 bit), and sometimes it makes sense to use flag enums where each individual bit in a series of bytes represents one element of the enum. Effectively allowing an enum value to represent two or more values simultaneously.

Why do you need to cast enums to ints or strings occasionally? Sometimes this is necessary for persistence (to database or other long term storage mechanism) or communication serialisation reasons.
In these examples I'll use this enum (generally for a non-flags enum you do not set the values): 

[Flags] 
public enum SomeFlags { Default = 4096, Email = 16384, Mobile = 32768, LandLine = 8192, Fax = 1, }

To and From Strings

SomeFlags x = SomeFlags.Email;
string str = x.ToString();
Variable str will now equal "Email".


SomeFlags x = (SomeFlags)Enum.Parse(typeof(SomeFlags), "Email");
Variable x will now be of type SomeFlags and set to value SomeFlags.Email. As you can see this method creates a rather bad dependency on those string enum names never changing.

Don't rely on Enum.GetName(Type, String) this will only work if there is an exact match.  If you are using a Flags enum and it is set to two or more values simultaneously (ie using a binary OR) this method  will not work.

To and From Integers
SomeFlags x = SomeFlags.Email; 
int value1 = (int)x;
Variable value1 is now equal to 16384.


int y = 16384;
SomeFlags x = (SomeFlags)Enum.ToObject(typeof(SomeFlags), y);
Variable x is now of type SomeFlags and is set to SomeFlags.Email.

Same comment as above applies here do not rely on Enum.GetName(Type, Int) this will not work for flag enums when they are set to two or more values simultaneously using a binary OR.

Other Casting
There is also a EnumConverter class, but you should never directly create this class. Rather call the GetConverter static method of the TypeDescriptor class. This converter is designed to handle the internals of how to convert to and from strings.

See Also
Don't forget about the other handy conversions available on the Convert static class. Especially the dynamic runtime convert Convert.ChangeType(destinationType, object).

Thursday, November 25, 2010

App.Config files vs INI files vs Registry

Here's a couple of links I have found on the topic:

Monday, November 22, 2010

New Blog Host

Looks like Google have bought blogger! I noticed there was a new app available in google/apps a few weeks ago. Thanks to Google's awesome marketing strategy, ie give stuff away for free, here's my revamped blog site! I originally only used the Google apps website because it was free and with a bit of effort I could post everything I need there. But now Blogger is available its a fully featured Blogging engine, there's no reason not to upgrade.

Thanks Google!

I will be copying all my old blog posts across here manually piece by piece as time progresses. The old site will continue to be available here:
http://blog2.rees.biz

Thursday, November 4, 2010

WCF Data Services - Reflection Provider

A colleague and I have spent some time lately exploring and finally implementing a WCF Data Service.  In a nut shell this is a service interface to expose a data model over a service boundary using Linq.  Exposing a data model over a service boundary is not that special, anyone can write a service that returns an array of objects and maybe some methods that take some criteria arguments allowing return of filtered objects.  What makes this special is the fact you access the data using Linq (with some obscure and advanced Linq features disabled). Linq allows a familar means of data access from the client's point of view, and out of the box provides a huge range of data filtering, grouping, paginating and lazy loading features.

So what is this "Reflection Provider" flavour of WCF Data Services? Other providers include "Entity Framework Provider" for exposing a EF model over the wire, and "Custom Provider"; see MSDN for more details.  The reflection provider works by pointing it at a class that defines a series of properties that return IQueryable.  This exposes all the sets your data model contains.  Each individual type can relate to other types in the model but each type must have a set property defined.  The beauty about this is most of the time you have an existing object model that can be exposed, all you need is a basic class to expose the IQueryable sets.

Obviously it would be easier to use Entity Framework, but in the problem I'm working on, there is no database, just a pre-loaded in memory object graph.  Exposing it to allow querying was pretty straight forward (with a few gotchas), and enabling editing of the object model is possible too.

Here's a sample application I wrote based on extending the example on MSDN,
Basic Example.

Here's a few gotcha's that my colleague and I found along the way:

  • Every type must have a DataServiceKeyAttribute. This must point to a unique "primary-key" property on the type.
  • References to sets, ie, the many side of a one to many relationship should be of type IList<T>.
  • Enums do not get shipped across the wire for some reason. There are plenty of requests on the forums to cater for this, hopefully will appear in a future release. This can be worked around by ignoring this property and having an equivelent int property. Use the IgnorePropertyAttribute to exclude a property. On the client side the enum can be partialled back in.
  • Don't forget to use the Linq Expand method to instruct WCF to return related sets of data, by default these get excluded.

Next I had a look at performance.  I compared it to a standard WCF service where you would have to write your own methods to provide ways of returning a sensible amount of data.  Seems like a crazy comparison to do I know, but it was necessary to prove a point.  Its pretty obvious that if you choose not to use WCF Data Services you will end up writing your own query language in the form of many OperationContracts. Using Linq is far less work and a huge amount of flexibility out of the box.


The long and short of it is Linq is actually faster due to a standard service is always going to return populated (eager) related sets. This means potentially huge graphs of data being served back when the client only will use one object.  You would be able to code a way to return only the object requested but its extra work and very proprietry and extra code to debug.

Thanks Marjorie for your input, great work!

Tuesday, October 26, 2010

Software Design Principles


Principles Of Software Design

8-September-2010


Established List of Design PrinciplesMy Principles

Four founding principles of object oriented design:
  1. Encapsulation
    .
    Organise like themed concepts into one unit (class) that performs one task or a group of similar tasks.  These units often mimic real world objects, for example an employee class may have a name attribute and a promote method. Encapsulation hides implementation details from the consumers, simplifying external use.


     
  2. Abstraction
    .
    The best definition of abstraction I've ever read is: "An abstraction denotes the essential characteristics of an object that distinguish it from all other kinds of object and thus provide crisply defined conceptual boundaries, relative to the perspective of the viewer." -- G. Booch. Encapsulation and Abstraction are closely linked and used together.  Referring to an object using an appropriate level of abstraction allows grouping of different objects together and treating them alike.



  3. Inheritance
    .
    Describes various levels of abstraction of an object. A cat class could inherit from Feline, which could inherit from Mammal which could inherit from Animal etc.  Each of these levels can describe attributes and actions common to all children that inherit.





  4. Polymorphism
    .
    By grouping different objects together that all have a common abstract parent actions can be performed on all the objects at once.





The Seven Fundamental Principles of Software Design (more classical / old school):
  1. The Reason it all exists.
    A software system exists for one reason: to provide value to its users. All decisions should be made with this in mind. Before specifying a system requirement, before noting a piece of system functionality, before determining the hardware platforms or development processes, ask yourself questions such as: "Does this add Real Value for the users of the system?" If the answer is "no", don t do it. Remember to think about it from your users point of view.
  2. Keep it simple.
    A good software design should be simple, elegant and exactly meet the requirements, no more, no less.  Creating a simple design is actually harder than creating a complicated one, and takes more time. Don't use this as a security blanket to not learn new skills however and stay current with available tools.
  3. Maintain the vision.
    A clear vision, project scope and requirements is absolutely essential.  A focused concept of what the system does at a high level helps give clear focus of each smaller component's. The system should not be stitched together like a patchwork of incorrectly fitted puzzle pieces.
  4. What you produce others will consume.
    No system is ever used in a vacuum. Someone will be attempting to use it, without instruction.  When was the last time you read a software instruction manual? No one reads these anymore. Your software must be intuitive and discoverable.  Sometimes your users are low skilled PC-users who will be using a UI to interact, other times they are developers consuming your API. Consider your audience.
  5. Be open to the future.
    Software written today will most likely far outlive today's hardware.  A strong software design will use the best technology and tools available to ensure the design will still be able to make use of tomorrow's hardware. All software projects should include time to ensure discovery of new tools and appropriate tools.
  6. Plan ahead for reuse.
    Write small reusable chunks of code. Each piece should be tightly themed and only concerned with one job. Consider not pushing this too far however, complexity will result.  Better to have a small amount of redundancy over excessive complexity.
  7. Think.
    Developers are detail people.  Each step along the way keep zooming out and clarifyng the big picture.

 Over time I have found these principles to both save time and clarify and provide clean software design, in no particular order.
  1. Don't fight the tools.
    If the tool does a job in a certain way, it will always be easier, faster and more maintainable to just suck it up and use the tool in the way it was intended to be used.
  2. Prefer generating straight forward code over a small amount of complex multipurpose generic code.
    A good example of this extensive use of reflection, rather prefer writing a code generator for use at design time that will generate all the permutations that the reflection would otherwise have catered for.  This gives an easier learning curve when looking at the resulting code and makes debugging far easier.
  3. Always challenge beliefs, look for facts and proof.
    If you think doing something one way might be better, find out why and prove with facts.  Or at least know you have proved it before and can again if need be.
  4. Get comfortable with Unit Testing.
    Its here to stay and will help you prove things quickly without having to write a great deal of test harness applications with a UI.
  5. Don't repeat yourself (DRY).
    Don't write the same piece of code twice in different places.
  6. Less code equals less testing, less bugs.
    Don't over engineer things and don't write code you are not using today.
  7. Patterns over technology.
    Always look for established modern patterns. New technology is good but if you can't use it to implement a well suited pattern, forget it.
 More Information:
 Other more focused principles:

There are five principles of class design (aka SOLID):
There are three principles of package cohesion
There are three principles of package coupling
-- RobertCecilMartin 19990907

Saturday, September 18, 2010

How to build a custom StyleCop Rule

18-September-2010

How to build a StyleCop Rule to enforce 'this' keyword use on fields.

First make sure you have the latest version of StyleCop.  I wrote my first rule against 4.4.  In my opinion, using StyleCop without Resharper and the StyleCop-For-Resharper plug-in is just plain silly.  These tools make it so easy to write code in accordance to established rules its trivial. Next you might find it very useful to download the full source for StyleCop, not necessary but I found it interesting.

Next you need to figure out how you are going to find the fragments not in accordance with your rule.  But first here's how StyleCop breaks down a file of code.

StyleCop Code File Structure
StyleCop breaks a code file down into Elements, statements and expressions.
Elements are large chunks of code, the red blocks below are elements. Basically, namespaces, types, and members.
Each statement line is obviously included in the statement category.  I never tested this by having two statements on one line, but having two statements one a line is an incredibly bad idea anyway, so you're on your own there. All lines above are included in this category except whitespace and braces.

Lastly each expression is then every granular item thereafter.  For example "this.apple = banana" is an expression and so is "this", ".", "=", and "\"banana\"".  The expression list therefore is significantly larger than the previous two categories.  Each expression also offers a list of child "tokens" which are the subordinate expressions to the current one.  The subordinate expressions will still be visited by the main loop despite being a child of some other expression.

StyleCop's Process 
StyleCop accepts three delegates from your custom rule, each one walking each of the above code element categories.  Ideally, if you can discover the fault with the line you can raise a Violation right away.  If not you will need to analyse the entire file then process the collected data afterwards.  (This is the case forJSL StyleCop rules - see below). Each of these expression tree walkers run on its own thread, so cannot easily share state during the process.  

Debugging a Rule
Ok, how to debug a rule?  I personally looked into writing unit tests against my rule, but found this far too tricky and time consuming.  The other option is to have two instances of Visual Studio open one to load some sample code, and the other with your rule code loaded and attach to the other's process.  The only downside to this, is when you make changes you will need to close both instances to update your DLL.  Suck it up, getting it done will be quicker than fiddling around with unit tests in this case. StyleCop isn't really designed for unit testing.  

More specifically you need to copy your built DLL than contains your rule into the StyleCop folder inside your Program Files (or Program Files (x86)) folder, just in the root StyleCop folder is fine (although sub-folders will be searched).  Your StyleCop assembly must also contain an XML file describing your rule.  This is the file StyleCop will use to add it to the Configuration tree.

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Extensions">
    <Description>
        These custom rules provide extensions to the ones provided with StyleCop.
    </Description>
    <Rules>
        <Rule Name="InstanceVariablesThisPrefix" CheckId="EX1001">
            <Context>Instance fields should be prefixed with the 'this' keyword.</Context>
            <Description>Instance variables (fields) are easier to distinguish and scope when prefixed with 'this'.</Description>
        </Rule>
    </Rules>
</SourceAnalyzer>


Build a 'This' Rule
In my case I am building a rule to enforce only the prefixing of fields with the 'this' keyword. There is a default StyleCop rule for this, but it enforces it in all instance cases (basically where it can be used it should).
I have achieved this by using the Expression delegate of the Analyse Document Walker.  I can't use the element part because this is not focusing on individual statements.  I have chosen not to use the statement walker delegate because I found it easier to discover the fields and check for violations using the expressions.

There's  some code clean up required on the code, but here it is:


namespace CustomStyleCopRules
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using Microsoft.StyleCop;
    using Microsoft.StyleCop.CSharp;

    /// <summary>
    /// This StyleCop Rule makes sure that instance variables are prefixed with this.
    /// </summary>
    [SourceAnalyzer(typeof(CsParser))]
    public class InstanceVariablesThisPrefix : SourceAnalyzer
    {
        private static readonly string RuleName = typeof(InstanceVariablesThisPrefix).Name;

        public override void AnalyzeDocument(CodeDocument document)
        {
            IDictionary<string, Field> fields = new Dictionary<string, Field>();

            var csdocument = (CsDocument)document;
            if (csdocument.RootElement == null || csdocument.RootElement.Generated)
            {
                return;
            }

            csdocument.WalkDocument(VisitElement, StatementWalker, ExpressionWalker, fields);
        }

        private static bool StatementWalker(Statement statement, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context)
        {
            return true;
        }

        private static bool VisitElement(CsElement element, CsElement parentElement, object context)
        {
            return true;
        }

        private static bool ExpressionWalker(Expression expression, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context)
        {
            try
            {
                if (parentElement != null && parentElement.Generated)
                {
                    return true;
                }

                var fields = context as IDictionary<string, Field>;
                if (fields == null)
                {
                    return true;
                }

                if (parentElement is Field)
                {
                    // We have found a field -  add it to the field collection. This assumes that fields are declared at the top
                    // of your class, which the of course they should be.
                    var field = parentElement as Field;
                    string name = field.VariableDeclarationStatement.Declarators.First().Identifier.Text;
                    if (field.Declaration.Tokens.Any(x => x.Text == "static") || field.Const)
                    {
                        // Ignore static fields. These do not require the 'this' prefix. So dont add them to the collection.
                        return true;
                    }

                    fields[name] = field;
                    return true;  // No need to check this expression further.
                }

                var tokens = expression.Tokens.ToArray();
                var keys = fields.Keys.ToArray();
                if ((expression.ExpressionType == ExpressionType.Literal && parentStatement.StatementType == StatementType.Return)
                    || (expression.ExpressionType == ExpressionType.Literal && parentStatement.StatementType == StatementType.Yield))
                {
                    // Check for already prefixed.
                    if (parentExpression == null || parentExpression.ExpressionType != ExpressionType.MemberAccess)
                    {
                        // short statements with no other tokens slip thru the cracks. Want to ignore singular literals,
                        // they have no children to figure out acceptability.
                        // for example return field; is one expression that has no child tokens that is an exception to this rule.
                        CheckForFieldUsingTokens(parentElement, expression, tokens, keys);
                    }
                }

                // Expressions that will never contain field references, an absence of tokens normally means a literal. We are unable to check
                // for compliance with the rule at this level because the 'this' part will be a sibling expression.  We need to check the parent
                // expression compliance by looking at it as a whole then looking at its tokens.
                if (expression.ExpressionType == ExpressionType.Literal || tokens.Length == 0)
                {
                    return true;
                }

                if (CheckForFieldUsingTokens(parentElement, expression, tokens, keys))
                {
                    return true;
                }

                return true;
            } catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

        private bool CheckForFieldUsingTokens(CsElement parentElement, Expression expression, CsToken[] tokens, string[] keys)
        {
            if (parentElement is Constructor)
            {
                // If its a constructor and there are duplicate names in the tokens this indicates a syntax like this
                // this.apple = apple; where apple is a constructor argument.  Ignore these as they will be handled by another
                // rule.
                // Find duplicate tokens and they are also field names
                var query = from token in tokens
                            where keys.Contains(token.Text) && tokens.Count(t => t.Text == token.Text) > 1
                            select token;
                if (query.Any())
                {
                    return true;
                }
            }

            for (int i = 0; i < tokens.Length; i++)
            {
                var token = tokens[i];
                if (keys.Contains(token.Text))
                {
                    if (i < 2)
                    {
                        this.AddViolation(parentElement, expression.LineNumber, RuleName, "Fields must be prefixed with the 'this' keyword.");
                        return true;
                    }

                    if (tokens[i - 1].Text != "." && tokens[i - 2].Text != "this")
                    {
                        this.AddViolation(parentElement, expression.LineNumber, RuleName, "Fields must be prefixed with the 'this' keyword.");
                        return true;
                    }
                }
            }

            return true;
        }
    }
}



Resources: