November 11, 2008

Cool Commands

Cool commands for VS2008 OR Alternative or use CoolCommands here. 1. Unzip coolcommandsrtm.zip (ie: c:\coolcommands ) 2. Open VS 2005 command prompt 3. run c:\coolcommands\install.bat but download from here.

IEnumerable, IEnumerator and foreach Implementation

IEnumerable - Provides an IEnumerator that can traverse a collection

public IEnumerator GetEnumerator();

IEnumerator - Methods to traverse a collection

public object Current;
public bool MoveNext();
// Ignore the next method, it should be marked as [Obsolete], just use GetIterator()
public void Reset(); 

This code shows in a simplistic manner how foreach is implemented using iterators. See here for more details

// foreach Implementation
IEnumerable enumerable = (IEnumerable)targObject;
IEnumerator it = enumerable.GetEnumerator();
while(it.MoveNext())
{
    DoSomething(it.Current);
}

Configuring Log4Net Programmatically

Configuring Log4Net Programmatically Set the logging level of the logger
public string LoggingLevel
{
 get
 {
  log4net.Repository.Hierarchy.Logger logger = (log4net.Repository.Hierarchy.Logger)m_log.Logger;
  return logger.Level.Name;
 }
 set
 {
  if (!string.IsNullOrEmpty(value))
  {
   log4net.Repository.Hierarchy.Logger logger = (log4net.Repository.Hierarchy.Logger)m_log.Logger;
   logger.Level = logger.Hierarchy.LevelMap[value];
  }
 }
}
Example configuring Appenders for a log
#region log4net

internal class LoggingConfigurer
{
    public static readonly string DefaultLayoutPattern = "%d [%t]%-5p %c [%x] - %m%n ";
    public static readonly string DefaultFileName = "XXXLog.txt";
    public static readonly string FileAppendarName = "XXXRFA";

    // Configure the logger programmatically. 
    public static void ConfigureLogging(ILog log)
    {
        bool isConfigured = log.Logger.Repository.Configured;
        if (!isConfigured)
        {
            // Setup RollingFileAppender
            RollingFileAppender rollingFileAppender = new RollingFileAppender();
            rollingFileAppender.Layout = new PatternLayout(DefaultLayoutPattern);
            rollingFileAppender.MaximumFileSize = "100KB";
            rollingFileAppender.MaxSizeRollBackups = 5;
            rollingFileAppender.RollingStyle = RollingFileAppender.RollingMode.Size;
            rollingFileAppender.AppendToFile = true;
            rollingFileAppender.File = DefaultFileName;
            rollingFileAppender.Name = FileAppendarName;
            rollingFileAppender.ActivateOptions(); // IMPORTANT, creates the file
            BasicConfigurator.Configure(rollingFileAppender);
#if DEBUG
            // Setup TraceAppender
            TraceAppender ta = new TraceAppender();
            ta.Layout = new PatternLayout(DefaultLayoutPattern);
            BasicConfigurator.Configure(ta);
#endif
        }
    }
}

#endregion log4net  
usage, when initialising your logger:
log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
LoggingConfigurer.ConfigureLogging(log);
Here is an example where the log file name is changed:
private static void RenameLogFile(string newLogFileName)
{
    var rfa = LogManager.GetRepository().GetAppenders().
         OfType<RollingFileAppender>().
         FirstOrDefault(appender => 
            appender.Name == LoggingConfigurer.FileAppendarName);
    if (rfa != null)
    {
        rfa.File = newLogFileName + ".txt";
        rfa.ActivateOptions();
    }
}

Delegating an Event Handler

// Say we have some event declared in one class
public event SomeStatusEventHandler SomeStatusEvent
{   // Delegate the event 'add' and 'remove' calls to the 'target' object
 add { this.target.SomeStatusEvent += value; }
 remove { this.target.SomeStatusEvent -= value; }
}
There is a sample of this in use in the Windows Service Class Example. Note that this syntax exposes an event for adding and removing event handlers but an event must be defined elsewhere that is to be exposed.
Say we have some private event declared in the same class:
private event SomeStatusEventHandler someStatusEvent;

public event SomeStatusEventHandler SomeStatusEvent
{   
 add { this.SomeStatusEvent += value; }
 remove { this.SomeStatusEvent -= value; }
}

Comparing Delegates, Anonymous Methods and Lambda Expressions

Here is a good link on this subject. Note the difference between a 'statement lambda' and an 'expression lambda'.
There are now 3 syntaxes for implementing delegates in C#. Here is the same code using the different syntax in each case:
1. Delegate
void StandardDelegateSample()
{
    ISomeResource[] resources =  someFacade.GetResources();
    ISomeResource target = Array.Find(resources, 
       new Predicate(FindTargetSomeResource));
}

// This method implements the test condition for the Find
// method.
private bool FindTargetSomeResource(ISomeResource res)
{
    return (res.Id == TARGET_ID);
}
2. Anonymous Method
void AnonymousMethodSample()
{
    ISomeResource[] resources =  someFacade.GetResources();
    ISomeResource target = Array.Find(resources, 
            delegate(ISomeResource res)
            {
                return (res.InformSourceId == TARGET_ID);
            }
    );
}
3. Lambda Expression
These are an even more shortened version of an anonymous delegate. The argument type can be missed out, the braces, and even the return statement. Like anonymous methods they can support variable capture from the encompassing method, ie. they can refer to the parameters or locals of the hosting method.
void LambdaExpressionSample()
{
  ISomeResource[] resources =  someFacade.GetResources();
  ISomeResource target = Array.Find(resources, 
    res => (res.InformSourceId == TARGET_ID) 
  );
}
Here are the 3 different forms of lambdas:
res => (res.Id == TARGET_ID) // simplest ('Expression Lambda') 
(ISomeResource res) => (res.Id == TARGET_ID) // specify parameter ('Expression Lambda')
(ISomeResource res) => { return (res.Id == TARGET_ID); } // Braces allow for multiple statements ('Statement Lambda')
However there is a gotcha with the use of anonymous methods (and lambda expressions?) so beware.
Code used to validate my lambda expressions:
public class LambdaExpressionTester
{
  public interface ISomeResource
  {
    int Id { get; set; }
              
    // ...
  }

  public class SomeResource : ISomeResource
  {
    public int Id { get; set; }
    //public string Name { get; set; } }
    // ...
  }

  private ISomeResource[] m_SomeResources = 
          new ISomeResource[] {
          new SomeResource{Id=1},
          new SomeResource{Id=4},
          new SomeResource{Id=11},
          new SomeResource{Id=43},
        };

  private static readonly int TARGET_ID = 11;

  public void LambdaExpressionSample()
  {
      ISomeResource[] resources = GetResources();
      ISomeResource target = Array.Find(resources, 
      res => (res.Id == TARGET_ID) 
      //(ISomeResource res) => (res.Id == TARGET_ID)
      //(ISomeResource res) => { return (res.Id == TARGET_ID); }
  );
  }

  private ISomeResource[] GetResources()
  {
      return m_SomeResources;
  }
}

Here is code to demonstrate all the forms of lambda expressions and anonymous delegates:
public void TestAllLambdaForms()
{
    int local = 3;

    // Implicitly typed lambda expression.
    Func<int, int> func1 = x => x+1;
            
    // Lambda expression with statement body.
    Func<int, int> func2 = x => { return x + 1; };

    // Lambda expression using formal parameters with expression body.
    Func<int, int> func3 = (int x) => x + 1;

    // Lambda expression using formal parameters with a statement body.
    Func<int, int> func4 = (int x) => { return x + 1; };

    // Lambda expression using multiple parameters.
    Func<int, int, int> func5 = (x, y) => x * y;

    // Lambda expression using multiple formal parameters.
    Func<int, int, int> func6 = (int x, int y) => x * y;

    // Lambda expression using with no parameters
    Action func7 = () => Console.WriteLine("blah blah blah");

    // Lambda expression accessing a local variable.
    Func<int, int> func8 = x => x * local;

    // Anonymous Method/Delegate with no parameter list.
    Func<int> func10 = delegate { return 1 + 1; };

    // Anonymous Method/Delegate method expression.
    Func<int, int> func11 = delegate(int x) { return x + 1; };

    // Anonymous Method/Delegate expression with 2 parameters.
    Func<int, int, int> func12 = delegate(int x, int y) { return x * y; };

    // Anonymous Method/Delegate accessing a local parameters.
    Func<int, int> func13 = delegate(int x) { return x * local; };

    Console.WriteLine("func1:" + func1.Invoke(1));
    Console.WriteLine("func2:" + func2.Invoke(1));
    Console.WriteLine("func3:" + func3.Invoke(1));
    Console.WriteLine("func4:" + func4.Invoke(1));
    Console.WriteLine("func5:" + func5.Invoke(2, 2));
    Console.WriteLine("func6:" + func6.Invoke(2, 2));
    Console.Write("func7:"); func7.Invoke();
    Console.WriteLine("func8:" + func8.Invoke(1));
    Console.WriteLine("func10:" + func10.Invoke());
    Console.WriteLine("func11:" + func11.Invoke(1));
    Console.WriteLine("func12:" + func12.Invoke(2, 2));
    Console.WriteLine("func13:" + func13.Invoke(1));
}
Here is the output:
func1:2
func2:2
func3:2
func4:2
func5:4
func6:4
func7:blah blah blah
func8:3
func10:2
func11:2
func12:4
func13:3

Calling WaitOne With A TimeOut

... 
AutoResetEvent finishedEvent = null;
...
finishedEvent = new AutoResetEvent(false);
try
{
 DoSomethingOnAnotherThread()
 // Wait until the 'finishedEvent' is 'Set()'
 // to tell us that the job is complete
 if (finishedEvent.WaitOne(TWENTY_SECONDS, false))
 {
  OnSuccess();
 }
 else // Timed out before event was called
 {
  OnTimedOut();
 }
}
finally
{
 finishedEvent.Close();
 finishedEvent = null;
}        

Exceptions

Top 10 Tips for Exception Handling in C#
Exception Types
Exception ClassCause
SystemExceptionA failed run-time check;used as a base class for other.
AccessExceptionFailure to access a type member, such as a method or field.
ArgumentExceptionAn argument to a method was invalid.
ArgumentNullExceptionA null argument was passed to a method that doesn't accept it.
ArgumentOutOfRangeExceptionArgument value is out of range.
ArithmeticExceptionArithmetic over - or underflow has occurred.
ArrayTypeMismatchExceptionAttempt to store the wrong type of object in an array.
BadImageFormatExceptionImage is in the wrong format.
CoreExceptionBase class for exceptions thrown by the runtime.
DivideByZeroExceptionAn attempt was made to divide by zero.
FormatExceptionThe format of an argument is wrong.
IndexOutOfRangeExceptionAn array index is out of bounds.
InvalidCastExpressionAn attempt was made to cast to an invalid class.
InvalidOperationExceptionA method was called at an invalid time.
MissingMemberExceptionAn invalid version of a DLL was accessed.
NotFiniteNumberExceptionA number is not valid.
NotSupportedExceptionIndicates sthat a method is not implemented by a class.
NullReferenceExceptionAttempt to use an unassigned reference.
OutOfMemoryExceptionNot enough memory to continue execution.
StackOverflowExceptionA stack has overflown.