Paste2 Logo
  1.     public class ExpandoObject : DynamicObject
  2.     {
  3.         private HashList<string, MulticastDelegate> _methods = new HashList<string, MulticastDelegate>();
  4.  
  5.         public void AddMethod<T>(string methodName, Action<T> methodBody)
  6.         {
  7.             MulticastDelegate targetDelegate = methodBody;
  8.             AddMethod(methodName, targetDelegate);
  9.         }
  10.         public void AddMethod(string methodName, Action methodBody)
  11.         {
  12.             MulticastDelegate targetDelegate = methodBody;
  13.             AddMethod(methodName, targetDelegate);
  14.         }
  15.  
  16.         public void AddMethod(string methodName, MulticastDelegate methodBody)
  17.         {
  18.             _methods.Add(methodName, methodBody);
  19.         }
  20.  
  21.         public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  22.         {
  23.             var context = new MethodFinderContext(args);
  24.             var methodName = binder.Name;
  25.  
  26.             result = null;
  27.             if (!_methods.ContainsKey(methodName))
  28.                 return false;
  29.  
  30.             var candidateMap = new Dictionary<MethodInfo, MulticastDelegate>();
  31.  
  32.             foreach (var currentDelegate in _methods[methodName])
  33.             {
  34.                 var currentMethod = currentDelegate.Method;
  35.                 candidateMap[currentMethod] = currentDelegate;
  36.             }
  37.  
  38.             var finder = new MethodFinder<MethodInfo>();
  39.             var bestMatch = finder.GetBestMatch(candidateMap.Keys, context);
  40.  
  41.             if (bestMatch == null)
  42.                 return base.TryInvokeMember(binder, args, out result);
  43.  
  44.             var targetDelegate = candidateMap[bestMatch];
  45.             var targetMethod = targetDelegate.Method;
  46.             var target = targetDelegate.Target;
  47.  
  48.             result = targetMethod.Invoke(target, args);
  49.  
  50.             return true;
  51.         }
  52.     }
  53.  
  54.     class Program
  55.     {        
  56.         static void Main(string[] args)
  57.         {
  58.             var expando = new ExpandoObject();
  59.             dynamic dynamicObject = expando;
  60.  
  61.             // Add the SayHello method
  62.             expando.AddMethod("SayHello", () => Console.WriteLine("Hello, World!"));
  63.             dynamicObject.SayHello();
  64.  
  65.             // Add the Say method
  66.             expando.AddMethod<string>("Say", (message) => Console.WriteLine(message));
  67.             dynamicObject.Say("Hello Again, World!");
  68.  
  69.             return;
  70.         }
  71.     }

An example that shows how one could use LinFu 2.x with C# 4.0's dynamic keyword to create types that can dynamically add methods to themselves at runtime.