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(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 { 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.Method("toto"); "toto".GenericMethod(); "toto".StringMethod(); Console.WriteLine(); Console.WriteLine("Binding the various methods using MethodManager..."); MethodManager.Bind(MethodBuilder.Method); MethodManager.Bind(MethodBuilder.Method); MethodManager.Bind(ExtensionMethods.StringMethod); MethodManager.Bind(ExtensionMethods.GenericMethod); MethodManager.Bind(ExtensionMethods.GenericMethod); Console.WriteLine(); Console.WriteLine("Using the methods with MethodCaller..."); new MethodCaller(42).CallMethod(); new MethodCaller(0.5f).CallMethod(); new MethodCaller("bla bla bla").CallMethod(); new MethodCaller(33).CallMethod(); new MethodCaller(666).CallMethod(); Console.WriteLine(); Console.WriteLine("And finally, we try to use the MethodManager asking for an uninitialized method..."); try { new MethodCaller('@').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(); TestBinding(); TestBinding(); TestBinding(); TestBinding(); TestBinding(); TestBinding(); TestBinding(); Console.WriteLine(); Console.WriteLine("That's it."); } static void TestBinding() { Console.WriteLine("The method for type " + typeof(T).Name + " is " + (MethodManager.IsBound() ? string.Empty : "not ") + "bound."); } } delegate void MethodDelegate(T value); static class MethodManager { static class MethodHolder { public static MethodDelegate Method; } public static void Bind(MethodDelegate method) { MethodHolder.Method = method; } public static void CallMethod(T value) { MethodHolder.Method(value); } public static bool IsBound() { return MethodHolder.Method != null; } } public class MethodCaller { T value; public MethodCaller(T value) { this.value = value; } public void CallMethod() { MethodManager.CallMethod(value); } } }