Project Description

These are my best thin and fun buddies in daily coding!

Introduction

In last 2 years I was too tight on schedule to maintain a blog, write essays, contribute to other projects (and my bad) making friends. So I decided to gather some of my stuff that saved my neck someday; here. My main concern here is to present minimal tools.

When it got somewhere, there will be a NuGet package.

Usage

Note: For a complete list of downloads, goto DOWNLOADS tab.

Developing Windows Services (With Ease)
Extracte Buddy.WinSvcTemplate.zip from last release (or from VSIX\packages directory in source) somewhere then run vsix file then lunch Visual Studio 2012 then create a project of type Buddy.WinSvcTemplate. Now you have a Svc.cs file and you only have to implement bodies of three methods (OnStart, OnStop and OnShutdown) in that class.

To change your service name, description, display name and start mode, edit Conf.cs in WinSvc directory.

To install or uninstall your service, you just supply -i or -u at the command line. For a list of available command line options supply -h.

Where am I?
Sometimes we need to specify where we are at the code; for example in logging. Here can help us with that; we just use Here.Member(), Here.FileLine(), Here.FileName() or Here.Spot() at any place in our code. For example we can log an error like this: LogError("error occurred at {0}", Here.FileLine()); . Try it with your choice of logging library

Note: This "Here" class works with .NET 4.5. Another Here class exist in .NET 4.0 compilation with a slightly different syntax (I have not tested this with older versions of .NET but it works fine with .NET 4.0).

Command Line Options
For this we use class Buddy.Args. Let see if user needs help:
var args = new Args();
var showHelp = args["help"].IsSupplied();

showHelp indicates that if we have one of these supplied at the command line: help, /help, -help or --help. Based on that we can decide to show the help or not:
if (showHelp) { /* showing the help at console */ }

Now let's see what args gives us according to different command line arguments:
Argument Return Value of args["show"]
show show
(/ or - or --)show show
(/ or - or --)show:val val
(/ or - or --)show=val val
(/ or - or --)show(: or =)"val with space" val with space

To check that is something actually is supplied or not just call the IsSupplied() extension method. That method can be used in other situations too, instead of checking object == null or it's default value.

There is also times that you want to provide more that one argument for a parameter like app.exe --put val1 val2. You can use args["put", 2] to tell args that you want to see if there is a parameter named 'put' and it has at most 2 arguments:
var switchWithArgs = args["put", 2];
if (switchWithArgs.IsSupplied()) { }

switchWithArgs is a string[] and if the switch is supplied then it's not null and it contains the arguments (if there is any).

Using INI Files
Just use var ini = new Ini(); and you have a ini file with the default name conf.ini. You can also use other constructors and provide whatever name (or path) you prefer.
To set a value for a parameter in a section you can use ini["section-name", "parameter-name"] = value; and to read it you can use var value = ini["section-name", "parameter-name"]; . A shorthand is also provided so you can use just the parameter name and ini will use a default section named 'conf' like ini["time"] = string.Format("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now); which assigns the current time value to a key named 'time' under 'conf' section.

Working with CSV
I have learnt an important thing: Always search inside .NET first! And yes; It's built-in! I've just added some tools to work with it more easily.

To write CSV:
using (var writer = new StreamWriter(path, false, Encoding.UTF8))
{
	for (int i = 0; i < 10; i++)
	{
		writer.WriteRecord(",", new object[] { i, "REC,#" + i });
	}
}

WriteRecord is an extension method for StreamWriter. And to read CSV:
var csv = new TextFieldParser(path, Encoding.UTF8);
csv.SetDelimiters(",");
foreach (string[] rec in csv.Records(false)) { /* process record */ }

TextFieldParser is inside .NET at Microsoft.VisualBasic.FileIO!

Marshalling and Unmarshalling Structs
First define and decorate your struct:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Sample
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string Name;

    [MarshalAs(UnmanagedType.U4)]
    public uint User;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
    public byte[] Tracking;

    public override string ToString()
    {
        return new
        {
            Name = Name,
            User = User,
            Tracking = Tracking.BinaryText()
        }.ToString();
    }
}

Now assume that we have initialized one:
var sample = new Sample();
sample.Name = "KAVEH";
sample.Tracking = dataBytes;
sample.User = 1;

We can get this struct as bytes by var bytes = sample.FromStruct(); and back to struct by sample = bytes.ToStruct<Sample>(); ! That's it!

Old Toys and New Tricks: Pipe
There is an operator in almost all of functional languages (at least in ML family) named Pipe. It was in Linux bash from the beginning. In short it is old! Pipe is used to feed the result of a computation (expression) to another computation. This way we have a chain of processing; It's just like nested function calls with supervision of a plumber friend! Instead of f(g(h(X))) we write x |> h |> g |> f (for example in F#).

Based on this idea I wrote this extension method Pipe. But in time I've found another usage for it (the new trick) and It's when I need an extension method but It will be used just at that one place; so defining a new extension method for being used just at one place is expensive. Now Pipe to rescue: Pipe can be used as a general purpose, generic Extension Method! For example we have Lines for a StreamReader but not a file path (string). We can use Pipe here:
var file = @"C:\existing-file.txt";
foreach (var line in file.Pipe(f => { return new StreamReader(f).Lines(); })) Console.WriteLine(line);

This code shows the file content line by line in console window.

Go's 'defer'
'defer' statement in Go is a very pragmatic way to ensure releasing allocated resource properly or execute a command on exit in a function. Much like finally clause in try-finally and Dispose in IDisposable in C#. Defer is based on IDisposable and provides a nice syntax with a safe way to ensure some actions will be done and end of IDisposable scope:
using (var defer = new Defer())
{
	var res = AllocateResource();
	defer.Also += () => DeallocateResource(res);

	Process();
}


Go's 'chan'
Channels in Go provide a mechanism for message passing concurrency. The Channel class provides same functionality.

Other Bits...(TODO)

Last edited Apr 2, 2013 at 11:26 PM by ksh2codeplex, version 25