Showing posts with label Tutorial. Show all posts
Showing posts with label Tutorial. Show all posts

Wednesday, February 25, 2009

Binding dynamic types in WPF using IronPython and DLR


What would be covered in this post?

- Creating classes in IronPython and comparing with C# classes. Adding public properties in IronPython class.

- Using classes/interfaces in IronPython class which is in the hosting assembly. For example, if the application hosting the DLR and executing the IronPython class at runtime has an interface IDyn, this article covers on how to use that interface within the Python script.

- Accessing the dynamic type created in the IronPython and making an instance of it.

- Finally, binding the dynamic type to WPF controls.

Pre-Requisites

Before, we get started, I recommend you go through the article I posted previously which shows how to use the IronPython engine within .NET applications. I will be using the same PythonEngine class with a new method added as shown below.

   1: public T GetDynamicType<T>(string scriptFile)


   2:         {


   3:             try


   4:             {


   5:                 var source = engine.CreateScriptSourceFromFile(scriptFile);


   6:                 source.Execute(scope);


   7:                 var SomeClass = engine.GetVariable(scope, "DynObject");


   8:                 var t = engine.Operations.Create(SomeClass);


   9:                 return (T)t;


  10:             }


  11:             catch (Exception ex)


  12:             {


  13:                 Debug.WriteLine(ex);


  14:             }


  15:             return default(T);


  16:         }





In the above method, we see that the engine (refer to the previous article, it would be useful if you want to understand it) creates an instance of ScriptSource object from the script file. Then we pass the current ScriptScope we created earlier and pass it to the Execute() method which would make the class be available to be used. Line 7 shows using GetVariable() on the engine and we pass the scope (which knows where the class we are looking for is) and also the name of the class, which is DynObject. Once we have the class (I assume its the IL, or at least i understood it that way), we use the Create() method on the engine passing the class which would return instance of that class. Then we simply return the instance by casting it to type T (a generic, so we use default(T) which is like null but for generics). So this method basically executes a python script and returns an instance of the class we specify. May be I would just refactor the method to make it look like shown below and which allows the method itself to be more generic than it is.





   1: public T GetDynamicType<T>(string scriptFile, string className)


   2:         {


   3:             try


   4:             {


   5:                 var source = engine.CreateScriptSourceFromFile(scriptFile);


   6:                 source.Execute(scope);


   7:                 var SomeClass = engine.GetVariable(scope, className);


   8:                 return (T)engine.Operations.Create(SomeClass);


   9:             }


  10:             catch (Exception ex)


  11:             {


  12:                 Debug.WriteLine(ex);


  13:             }


  14:             return default(T);


  15:         }




The method is used as shown below.





   1: object o = pe.GetDynamicType<Object>("DynObject.py", "DynObject");




Creating IronPython class with public properties



Consider the C# class shown below.





   1: public class DynObject : IDyn 


   2: {


   3:    public string Name { get; set; }


   4:    public string Age  { get; set; }


   5: }




The class is named DynObject which implements the interface IDyn and which has two public properties Name and Age. The python code for the same is shown below.





   1: class DynObject(IDyn):


   2:   


   3:   def __init__(self): # this is the constructor


   4:     self._name = None # initialized to NULL


   5:     self._age = None # initialized to NULL


   6:     


   7:   def __getName(self):


   8:     return self._name


   9:     


  10:   def __getAge(self):


  11:     return self._age  


  12:     


  13:   def __setName(self,value):


  14:     self._name = value


  15:     


  16:   def __setAge(self,value):


  17:     self._age = value


  18:     


  19:   Name = property( # this is the Name property. use "property"


  20:      fget= __getName, # getter


  21:      fset= __setName  # setter


  22:   )


  23:   


  24:   Age = property(


  25:      fget=__getAge,


  26:      fset=__setAge


  27:   )






The statement followed by # are the comments. Hope they help you relate the classes properly and with that one should be able to write basic classes on their own.



Importing Namespaces in IronPython and setting up default namespaces



Now the problem with the above script when you Execute() it in the method I first discussed is that it would complain about not knowing what IDyn is. So basically we do an import the namespace. But the interface IDyn was created inside a namspace “Dynamics” which is the same application that is executing the python script. Had it been a ‘Debug’ then one could have done the following to import System.Diagnostics.*





   1: import clr


   2: clr.AddReference("System.Diagnostics")


   3: from System.Diagnostics import *


   4: # from System.Diagnostics import Debug 


   5: # if you just want to import Debug class




But the issue I has was to know what assembly should I mention in the AddReference and I was wondering if there was a good way to import some default namespaces into the engine without having the user mention them manually. For that reason we have ScriptRuntime.LoadAssembly(Assembly asmToLoad) which can be used to add reference to assemblies of your choice. In order to support this, I felt that it would be a good idea to load the assemblies before you even generate the ScriptSource object from the script file. For this reason, I modified the PythonEngine (the wrapper I talked about in my previous post on IronPython) constructor and now it looks like as shown.





   1: private PythonEngine(){


   2:             engine = Python.CreateEngine(new Dictionary<string, object>() { 


   3:                 { 


   4:                 "DivisionOptions", PythonDivisionOptions.New 


   5:                 } //using Dictionary Initializer ;)    


   6:             });


   7:             var runtime = engine.Runtime;


   8:             //Load the assemblies into the engine's runtime.


   9:             runtime.LoadAssembly(typeof(Debug).Assembly);


  10:             runtime.LoadAssembly(typeof(string).Assembly);


  11:             runtime.LoadAssembly(typeof(IDyn).Assembly);


  12:             scope = engine.CreateScope();


  13: }




What should be of interest to import default assemblies into the system are in lines 7-11. Then on we can move on to add the imports to the python file as shown. No more AddReference() required.





   1: from System.Diagnostics import Debug


   2: from Dynamics import IDyn


   3:  


   4: class DynObject(IDyn):


   5:   


   6:   def __init__(self):


   7:     Debug.WriteLine("here")


   8:     self._name = "buddi"


   9:     self._age = "22"


  10:     


  11:   def __getName(self):


  12:     return self._name


  13:     


  14:   def __getAge(self):


  15:     return self._age  


  16:     


  17:   def __setName(self,value):


  18:     self._name = value


  19:     


  20:   def __setAge(self,value):


  21:     self._age = value


  22:     


  23:   Name = property(


  24:      fget= __getName,


  25:      fset= __setName


  26:   )


  27:   


  28:   Age = property(


  29:      fget=__getAge,


  30:      fset=__setAge


  31:   )




Note that you still need to do the “from  NAMESPACE import CLASSNAME/*”.



How about integrating the python code in WPF?



The IDyn was just an empty interface which was added to explain how one could use .NET interfaces within IronPython classes. So back to the WPF application, which is simple and straight forward. The XAML code for the Window is shown below.





   1: <Window x:Class="DynamicBinding.Window1"


   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"


   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"


   4:     Title="Window1" Height="300" Width="300">


   5:     <StackPanel>


   6:         <TextBlock Text="{Binding Name}" Background="Red" Margin="5" Height="30"/>


   7:         <TextBlock Text="{Binding Age}" Background="Blue" Margin="5" Height="30"/>


   8:     </StackPanel>


   9: </Window>




From the bindings shown above, the Name property is looked for in the DataContext of TextBlock, StackPanel or Window. So in the code-behind we use our PythonEngine to obtain an instance of the dynamic type we created and set the DataContext of the window to the instance we obtained. The code behind is shown below.





   1: using System;


   2: using System.Windows;


   3: using Dynamics;


   4:  


   5: namespace DynamicBinding


   6: {


   7:     /// <summary>


   8:     /// Interaction logic for Window1.xaml


   9:     /// </summary>


  10:     public partial class Window1 : Window


  11:     {


  12:         private PythonEngine pe = PythonEngine.Engine;


  13:  


  14:         public Window1()


  15:         {


  16:             InitializeComponent();


  17:             object o = pe.GetDynamicType<Object>("DynObject.py", "DynObject");


  18:             this.DataContext = o;


  19:         }


  20:     }


  21: }




This ability to bind WPF controls to dynamic types would be a great feature if you would like to generate UI based on the user controlled params. This would be even easier with the dynamic support in C# 4.0 which I hope to see another release during the MIX 2009.



Next I would like to work on generate the python classes from XML which would be provided by the user and even the XAML would be generated from the XML. This would be the basis for my reporting suite which would be powered by Silverlight, DLR and WCF.

Sunday, January 27, 2008

.NET 3.5 : VB and C#

[The code in this post appears weird for some reasons, I used LiveWriter and few good but buggy plugins to attach code]

I recently made a list of ASP.NET Videos that are out there online. Excluding the MSDN Nuggets and Microsoft Webcast events, the listings spanned over 4 pages!!! I am really concerned and am cursing myself for not having watched any of those for years. I have actually been a close follower of videocasts/screencasts right from those days when there weren't that many online for free. Now Microsoft, I should say is the largest provider of screencasts, of course only about MS technologies and yet there are tons of their videos that I should be watching. (Of course, lets not forget about Channel 9 where there are quiet a lot more screencasts about everything from MS)

Anyway there is also this dnrTV.com which is run by .NET Rocks guys and provides .NET TV Sessions. The most recent two shows are really something that everyone who is learning .NET should watch. It is by Kathleen Dollard and gives a first hand explanation about .NET 3.5 and shows VB 9.0 and C# 3.0 side by side which is really something! The actual show can be watched here.

I am writing down some important points for my own use and others might find it useful. I hope I am not violating any rights(hopefully).The disclaimer is that the images shown below is taken from the show using Snipping Tool which is shipped along with Windows Vista. This is not my work and I hope not to make any violations. In case of any, please let me know so that I can remove this post online.
Anyway my notes follows ....

.NET 3.5 Assemblies:

.NET 3.5 The important aspect is that .NET 3.5 still has the same Core - .NET 2.0. Simply put .NET 3.5 is nothing but .NET 3.0 plus additional features and we know that .NET 3.0 is nothing but .NET 2.0 Core plus few amazing libraries like the WPF, WCF, WF, CardSpace. It is also mentioned by Kathleen that Speech library is shipped in the .NET 3.0 and it is not that well known.

.NET Versions

.NET Versions There have been five versions of .NET till date. While VB 7 and C# was for .NET 1.0 and 1.1; VB 8 and C# 2.0 was for .NET 2.0 and .NET 3.0.

Now the brand new C# 3.0 and VB 9.0 adds a lot of new features makes programming in these languages very exciting.

Anyway the slides look amazing, you should watch the show without fail if you are interested!


Nullable in VB vs. C#

Declaring Nullable in VB

   1: Dim x as Nullable(Of Boolean) = False
   2: Dim y as Boolean? = False   

C# Nullables and bit more code to help you understand what Nullables are!


   1: bool? x = null;
   2: if(x.HasValue)
   3:  Console.WriteLine("x does have a value!");
   4: else
   5:  Console.WriteLine("x do not have a value and is null!");
   6: bool? y = x.GetValueOrDefault(); //y is initialized to false!
   7: Console.WriteLine("y is "+y);

Differences:

Suppose x and y are nullable booleans and x is set to null/nothing while y is set to false. Look at these:
x == y => False in C# and Nothing is VB (since one of them is nothing!). So can you guess the output of the following VB code snippet!

   1: Dim x As Nullable(Of Boolean) = Nothing    
   2: Dim y As Boolean = Nothing    
   3: Console.WriteLine("x = " + ((x = y) Is Nothing).ToString)


Another note for beginners! Consider the C# code:

   1: Employee emp = null;    
   2: if(emp==null)    
   3:  Console.WriteLine("Emp object is set to null!");

The equivalent VB code is:

   1: Dim emp as Employee = Nothing    
   2: If(emp = Nothing) 'This does not return true, = Nothing is not equivalent to == null    
   3:  Console.WriteLine("You would not see this line in the output!")    
   4: If emp Is Nothing ' This is how you check for null!    
   5:  Console.WriteLine("emp Object is set to null!")


If you read the above code snippet, I have conveyed the message in the comment on Line 2.

Frankly there are lot more differences with respect to how operators work differently in C# than in VB. Simply put the key point to remember is that

In Visual Basic, comparison between anything that is null(Nothing) to anything else returns Null/Nothing!!

In C#, you cannot use any operator but == on boolean

Note: By the way a great tool for .NET Developers in Snippet Compiler!

Operators in VB vs C#

Ternary Operator in C#:

   1: bool buddi = false;    
   2: string nameOfBuddi = buddi?"Bhargav":"Someone";    
   3: Console.WriteLine("Buddi is "+nameOfBuddi); //Displays "Someone"    
   4: buddi = true;    
   5: Console.WriteLine("Buddi is "+buddi?"Bhargav":"Someone"); //Displays "Bhargav"

Ternary Operator in VB:

IIf was used as ternary operator in VB but it is actually a function! But in VB 9.0, IIF is an operator! The actual difference would be understood when you look at this snippet:
   1: Shared Sub Main()    
   2:   Console.WriteLine(IIf(true,Method1(),Method2()))    
   3: End Sub    
   4:      
   5: Function Method1 as Integer    
   6:     Console.WriteLine("Method 1")    
   7:     Method1 = 1    
   8: End Function    
   9:      
  10: Function Method2 as Integer    
  11:     Console.WriteLine("Method 2")    
  12:     Return 5    
  13: End Function


The output of the above snippet is

Method 1
Method 2
1

As you can see, Method1() and Method2() are first evaluated and then the appropriate return value is returned. Here since its true, return value of Method1() is returned on the screen.

Another note for beginners, in Visual Basic, you can return a value in two ways. The first way is shown in the above code snippet in Line 7 where you assign FunctionName = returnValue and the second way is to use return keyword, like in other languages. You can use which ever makes more sense to you, well based on your choice.

The next few features were actually present in earlier versions of VB and unavailable in C# ( the above talked features were in C# only until VB 9.0)

Contd...