1. // -------------------------------------------------------------------------------------
  2. // This is an example from a blog post over at Dev Leader. Check it out:
  3. // http://www.devleader.ca/2013/10/01/dynamic-python-c/
  4. //
  5. // Follow Dev Leader:
  6. // Facebook - http://www.facebook.com/DevLeaderCa
  7. // Google+ - https://plus.google.com/b/108985236662325804542/108985236662325804542/posts
  8. // Twitter - http://www.twitter.com/nbcosentino
  9. // -------------------------------------------------------------------------------------
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13.  
  14. using Microsoft.CSharp.RuntimeBinder;
  15.  
  16. using IronPython.Hosting;
  17.  
  18. namespace DynamicClass
  19. {
  20.     internal class Program
  21.     {
  22.         private static void Main(string[] args)
  23.         {
  24.             Console.WriteLine("Press enter to read the value of 'MyProperty' from a Python object before we actually add the dynamic property.");
  25.             Console.ReadLine();
  26.  
  27.             // this script was taken from this blog post:
  28.             // http://znasibov.info/blog/html/2010/03/10/python-classes-dynamic-properties.html
  29.             var script =
  30.                 "class Properties(object):\r\n" +
  31.                 "    def add_property(self, name, value):\r\n" +
  32.                 "        # create local fget and fset functions\r\n" +
  33.                 "        fget = lambda self: self._get_property(name)\r\n" +
  34.                 "        fset = lambda self, value: self._set_property(name, value)\r\n" +
  35.                 "\r\n" +
  36.                 "        # add property to self\r\n" +
  37.                 "        setattr(self.__class__, name, property(fget, fset))\r\n" +
  38.                 "        # add corresponding local variable\r\n" +
  39.                 "        setattr(self, '_' + name, value)\r\n" +
  40.                 "\r\n" +
  41.                 "\r\n" +
  42.                 "    def _set_property(self, name, value):\r\n" +
  43.                 "        setattr(self, '_' + name, value)\r\n" +
  44.                 "\r\n" +
  45.                 "    def _get_property(self, name):\r\n" +
  46.                 "        return getattr(self, '_' + name)\r\n";
  47.  
  48.             try
  49.             {
  50.                 var engine = Python.CreateEngine();
  51.                 var scope = engine.CreateScope();
  52.                 var ops = engine.Operations;
  53.  
  54.                 engine.Execute(script, scope);
  55.                 var pythonType = scope.GetVariable("Properties");
  56.                 dynamic instance = ops.CreateInstance(pythonType);
  57.  
  58.                 try
  59.                 {
  60.                     Console.WriteLine(instance.MyProperty);
  61.                     throw new InvalidOperationException("This class doesn't have the property we want, so this should be impossible!");
  62.                 }
  63.                 catch (RuntimeBinderException)
  64.                 {
  65.                     Console.WriteLine("We got the exception as expected!");
  66.                 }
  67.  
  68.                 Console.WriteLine();
  69.                 Console.WriteLine("Press enter to add the property 'MyProperty' to our Python object and then try to read the value.");
  70.                 Console.ReadLine();
  71.  
  72.                 instance.add_property("MyProperty", "Expected value of MyProperty!");
  73.                 Console.WriteLine(instance.MyProperty);
  74.             }
  75.             catch (Exception ex)
  76.             {
  77.                 Console.WriteLine("Oops! There was an exception while running the script: " + ex.Message);
  78.             }
  79.  
  80.             Console.WriteLine("Press enter to exit...");
  81.             Console.ReadLine();
  82.         }
  83.     }
  84. }