Archive

Archive for the ‘Open Source’ Category

Windows Live Writer: Plug-ins to Format Content through CSS Classes

September 30th, 2009

I like using CSS classes to format specific content of my blog posts, in order to keep my formatting centralized. I prefer HTML that looks like this over inline styles:

If you invoke the <span class="code">GetData</span> method, ...

 

Quickly inserting CSS directives is something you can’t easily do with Windows Live Writer. This started to annoy me while writing an article, so I came up with two simple plug-ins that do just that: Formatting selected text through CSS classes.

 

Read more…

Snippet Time: Helper Libraries for C# / WPF

September 14th, 2009

I just made a few minor updates to two libraries which assemble as set of helper classes for C# and WPF and thought: Why not share them? The libraries aren’t really intended to be used directly in your code, but you might find one or another helper method or snippet that might make a nice addition to your own toolbox :)

 

Hardcodet.Commons (C#, .NET 3.5)

Common helper classes and snippets (simple base classes, file management, weak events, extension methods etc.)

 

Hardcodet.Wpf.Commons (C#, .NET 3.5)

Stuff I commonly use in WPF projects, such as checking for design time, base classes for commands and converters, data binding helpers and other stuff.

 

I’ll keep these libraries up-to-date, version history will be posted here.

 

History:

2009.09.14  Initial blog release

Tags: , ,

WPF NotifyIcon 1.0.1 – Minor Improvements, Major Tutorial

May 15th, 2009

I just posted an upgrade to my WPF NotifyIcon, which adds some minor improvements to the control. The most important one is probably the simplified data binding support for context menus (thanks to Nic Pillinger for the hint), but I also managed to add some polish in a few other areas.

 

image

 

Apart from the updated control itself, I completely revamped the sample project. It’s no longer just a showcase but contains various standalone samples which cover all aspects of the control. And last but not least, I published a complementary tutorial on the CodeProject. One could say I was quite busy ;)

 

Further information and download on the project page:
http://www.hardcodet.net/projects/wpf-notifyicon

NetDrives 1.0 Released

May 6th, 2009

NetDrivesI’ve just uploaded installer and source code of NetDrives 1.0. This is my first tool that does not only address fellow developers, but a wider audience :)

In a few words, NetDrives is an open source utility that helps you manage your network shares and mapped network drives. Unlike Windows, it can reconnect to secured shares during startup and provides you quick access to your configured shares.

 

quickaccess

 

More information, screenshots, and downloads at the project page:

http://www.hardcodet.net/netdrives

WPF NotifyIcon Released

May 4th, 2009

I’m happy to announce the public release of my WPF NotifyIcon control :-)

This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the existing Windows Forms component, but is a purely independent control which leverages several features of the WPF framework in order to display rich ToolTips, Popups, context menus, and balloon messages.

 

image

 

I’m planning on doing an introductory article on CodeProject (well, somewhere along the way…) but you’ll probably get along just fine – the control comes with a sample application that shows off most of the control’s features.

 

Further information and download on the project page:
http://www.hardcodet.net/projects/wpf-notifyicon

 

kick it on DotNetKicks.com

Tags: ,

A Façade for Simple and Framework-Independent Logging in .NET

April 23rd, 2009

Logging is an important aspect, but I don’t like to have dependencies on a specific logging framework all over the place. This is where a logging façade comes in handy. Basically, a façade just provides you with a common interface that decouples the used logging framework from your code:

 

//ILogger is the facade. Behind the scenes,
//a framework of your choice is used
ILogger logger = LoggerService.Logger;
logger.Log("hello world");

 

The idea of a logging façade isn’t exactly new, but I thought I’d share this one with you for a few reasons:

  • It is dead easy to use.
  • It provides quite a few overloads when it comes to logging.
  • The core library has no dependencies on other libraries at all.
  • There are two façades (separate DLLs) that log through the Enterprise Library Logging block or the BitFactory logger. And hopefully more to come!
  • Writing your own façade is as simple as overriding one single method.
  • It’s not part of another project (completely standalone), and there is no license attached to it. Do with it whatever you want.
  • It is dead easy to use.

 

image

(click on image to enlarge)

 

Here’s one way to create a file-based logger (using the BitFactory façade) and make it globally accessible. This only takes you a few lines of code:

//create a new logger instance
string file = @"C:\logfile.txt";
ILogger logger = BitFactoryLogger.CreateSingleFileLogger(file);

//use the global LoggerService to store the logger
LoggerService.SetLogger(logger);

...

//this will store the info in the log file
LoggerService.Logger.Log("This is an information");

 

 

Logging via ILogger

The whole purpose of this project is to shield your libraries from the actually chosen logging framework. Accordingly, you are always logging through the ILogger instance. ILogger provides quite a few overloads of the Log method, here are a few of them:

 

public void LogData(ILogger logger)
{
  logger.Log("An information");
  logger.Log("Something Happened", TraceEventType.Warning);

  //LogItem is the most verbose version
  LogItem item = new LogItem();
  item.Message = "My Message";
  item.EventId = 999;
  item.Categories.Add("Foo");
  item.Priority = 10;
  logger.Log(item); 

  try
  {
    DivideByZero();
  }
  catch(Exception e)
  {
    logger.Log(e);
    logger.Log("Additional message.", e);
    logger.Log("Additional message.", e, TraceEventType.Critical);
  }
}

 

 

Initializing an ILogger Implementation

During the initialization of your application, you will have to specify the the logger implementation that is supposed to be used. This might happen declaratively or directly in code. Here’s the initialization code from NetDrives, which makes a logger available through the AutoFac IOC container.

Note that I’m registering a ConsoleLogger for debug builds, while release builds write into a log file. These are completely different classes, but it doesn’t matter - they both implement the ILogger interface:

 

//init IOC container builder
var builder = new ContainerBuilder();

//register single logger instance
ILogger logger;

#if (DEBUG)
  logger = new ConsoleLogger();
#else
  logger = BitFactoryLogger.CreateSingleFileLogger(AppUtil.LogFile);
#endif

//register logger
builder.Register(logger).As<ILogger>();

 

 

Registration and Access through LoggerService

I prefer to initialize and access my logger through an IOC container, but you can do it however you like. If you’re lacking a place to make your ILogger globally accessible, you can use the static LoggerService class:

 image

 

public void InitApp()
{
  //create a file logger (use BitFactory facade)
  string logFile = @"C:\MyLogFile.txt";
  ILogger logger = BitFactoryLogger.CreateSingleFileLogger(logFile);

  //register as globally used logger
  LoggerService.SetLogger(logger);
}

private void Foo()
{
  try
  {
    DoSomethingWrong();
  }
  catch(Exception e)
  {
    //get registered logger and log exception
    ILogger logger = LoggerService.Logger;
    logger.Log(e);
  }
}

 

A nice thing about LoggerService: It guarantees you always a valid ILogger instance. If no logger is set, it just falls back to a NullLogger implementation that does not create any output at all. Here’s the implementation:

 

namespace Hardcodet.Util.Logging
{
  /// <summary>
  /// Provides a global repository for a given <see cref="ILogger"/>
  /// instance. This class ensures that the <see cref="Logger"/>
  /// property is never nullo - in case no logger is defined, it
  /// automatically installs a <see cref="NullLogger"/>
  /// instance.
  /// </summary>
  public static class LoggerService
  {
    private static ILogger logger = new NullLogger();

    /// <summary>
    /// Gets the installed <see cref="ILogger"/> implementation.
    /// </summary>
    /// <remarks>This property always returns a valid
    /// logger.</remarks>
    public static ILogger Logger
    {
      get { return logger; }
    }

    /// <summary>
    /// Installs a given logger or resets the <see cref="Logger"/>
    /// to a <see cref="NullLogger"/> instance if the
    /// <paramref name="loggerImplementation"/> is a null
    /// reference.
    /// </summary>
    /// <param name="loggerImplementation">The logger to be
    /// used globally, or a null reference in order to reset
    /// the service.</param>
    public static void SetLogger(ILogger loggerImplementation)
    {
      logger = loggerImplementation ?? new NullLogger();
    }
  }
}

 

 

Creating a new Logger Façade

In case you want to use another logging framework (e.g. NLog or Log4Net), creating a new façade is very easy. Basically, you create a new project, set a reference to the base library and write a class that either

  • implements ILogger directly
  • or, even simpler, derives from the abstract LoggerBase class.

 

Feel like sharing your own façade? Just contact me and I’ll happily include your implementation :-)

 

As a sample, here’s the code of the ConsoleLogger (part of the core library) and the Enterprise Library façade:

 

using System;

namespace Hardcodet.Util.Logging
{
  /// <summary>
  /// A very simple implementation of <see cref="ILogger"/>
  /// that outputs all messages to the system console.
  /// </summary>
  public class ConsoleLogger : LoggerBase
  {
    /// <summary>
    /// Logs a given item to the console.
    /// </summary>
    /// <param name="item">The item to be logged.</param>
    /// <exception cref="ArgumentNullException">If <paramref name="item"/>
    /// is a null reference.</exception>
    public override void Log(LogItem item)
    {
      if (item == null) throw new ArgumentNullException("item");
      Console.Out.WriteLine(item.ToLogMessage());
    }

  }
}

 

 

 

using Microsoft.Practices.EnterpriseLibrary.Logging;

namespace Hardcodet.Util.Logging.EntLibFacade
{
  /// <summary>
  /// An implementation of the <see cref="ILogger"/>
  /// interface which outputs logged data using
  /// the <see cref="Logger"/> of the MS Enterprise
  /// Library.
  /// </summary>
  public class EnterpriseLibraryLogger : LoggerBase
  {

    /// <summary>
    /// Writes a log entry to the Enterprise Library's
    /// logging block. Output depends on the logging
    /// block's configuration.
    /// </summary>
    /// <param name="item">An log item which encapsulates
    /// information to be logged.</param>
    public override void Log(LogItem item)
    {
      LogEntry entry = ConvertLogItem(item);
      Logger.Write(entry);
    }

    /// <summary>
    /// Creates a <c>LogEntry</c> instance which can be processed
    /// by the Enterprise Library based on a given log item. 
    /// </summary>
    /// <param name="item">An log item which encapsulates information
    /// to be logged.</param>
    /// <returns>An Enterprise Library item which corresponds
    /// to the submitted <c>LogItem</c>.</returns>
    private static LogEntry ConvertLogItem(LogItem item)
    {
      //assign properties
      LogEntry entry = new LogEntry();
      entry.Message = item.Message;
      entry.Title = item.Title;
      entry.AddErrorMessage(item.ErrorMessage);
      entry.EventId = item.EventId;
      entry.Priority = item.Priority;
      entry.Severity = item.Severity;
      entry.TimeStamp = item.TimeStamp;

      foreach (string category in item.Categories)
      {
        item.Categories.Add(category);
      }

      return entry;
    }

  }
}

 

 

The download contains the core library, two external façades (BitFactory, Enterprise Library), and a sample project. Hope you’ll like it :-)

hardcodet-logging.zip

Tags: