File: Program.cs - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

���using System;

namespace GenericMethodBinder
{
 static class ExtensionMethods
 {
  public static void StringMethod(this string text)
  {
   Console.Write("This the specific extension method for the type string with the text ");
   Console.WriteLine(text);
  }

  public static void GenericMethod<T>(this T value)
  {
   Console.Write("This is the generic Extension Method for the type ");
   Console.Write(typeof(T).ToString());
   Console.Write(" called with the value ");
   Console.WriteLine(value.ToString());
  }
 }

 static class MethodBuilder<T>
 {
  static string text;

  static MethodBuilder()
  {
   text = "This is the generic Method for the type " + typeof(T).Name + " called with the value ";
  }

  public static void Method(T value)
  {
   Console.Write(text);
   Console.WriteLine(value.ToString());
  }
 }

 class Program
 {
  static void Main(string[] args)
  {
   Console.WriteLine("We are going to play with three method types:");
   Console.WriteLine(" - Method from a generic type, using the type parameter");
   Console.WriteLine(" - Generic extension method");
   Console.WriteLine(" - Specific extension method (which is the same as a regular method)");
   Console.WriteLine("Direct usage of the methods with the string type, just to show you what happens...");
   MethodBuilder<string>.Method("toto");
   "toto".GenericMethod();
   "toto".StringMethod();
   Console.WriteLine();

   Console.WriteLine("Binding the various methods using MethodManager...");
   MethodManager.Bind<int>(MethodBuilder<int>.Method);
   MethodManager.Bind<float>(MethodBuilder<float>.Method);
   MethodManager.Bind<string>(ExtensionMethods.StringMethod);
   MethodManager.Bind<short>(ExtensionMethods.GenericMethod);
   MethodManager.Bind<double>(ExtensionMethods.GenericMethod);
   Console.WriteLine();

   Console.WriteLine("Using the methods with MethodCaller...");
   new MethodCaller<int>(42).CallMethod();
   new MethodCaller<float>(0.5f).CallMethod();
   new MethodCaller<string>("bla bla bla").CallMethod();
   new MethodCaller<short>(33).CallMethod();
   new MethodCaller<double>(666).CallMethod();
   Console.WriteLine();

   Console.WriteLine("And finally, we try to use the MethodManager asking for an uninitialized method...");
   try
   {
    new MethodCaller<char>('@').CallMethod();
    Console.WriteLine("And the call is successful.");
   }
   catch (NullReferenceException e)
   {
    Console.WriteLine("And the call is unsuccessful.");
    Console.WriteLine(e.Message);
   }
   Console.WriteLine();

   Console.WriteLine("We could check the bindings before trying to use them, like this: ");
   TestBinding<int>();
   TestBinding<string>();
   TestBinding<float>();
   TestBinding<decimal>();
   TestBinding<double>();
   TestBinding<char>();
   TestBinding<byte>();
   TestBinding<short>();
   Console.WriteLine();

   Console.WriteLine("That's it.");
  }

  static void TestBinding<T>()
  {
   Console.WriteLine("The method for type " + typeof(T).Name + " is " + (MethodManager.IsBound<T>() ? string.Empty : "not ") + "bound.");
  }
 }

 delegate void MethodDelegate<T>(T value);

 static class MethodManager
 {
  static class MethodHolder<T>
  {
   public static MethodDelegate<T> Method;
  }

  public static void Bind<T>(MethodDelegate<T> method)
  {
   MethodHolder<T>.Method = method;
  }

  public static void CallMethod<T>(T value)
  {
   MethodHolder<T>.Method(value);
  }

  public static bool IsBound<T>()
  {
   return MethodHolder<T>.Method != null;
  }
 }

 public class MethodCaller<T>
 {
  T value;

  public MethodCaller(T value)
  {
   this.value = value;
  }

  public void CallMethod()
  {
   MethodManager.CallMethod(value);
  }
 }
}