Dynamic Languages and The .Net Framework - Promo #4 - With Our Powers Combined
This is the 4th part of my series about dynamic languages in the .Net framework. You can read the rest of the series here:
This time, I'm going to show you a sneak peek of the great things you can do with .Net and dynamic languages powers combined.
Ruby allows you to extend every class you want - very similar to .Net's extension methods. IronRuby allows you the same thing, with the added possibility to extend .Net objects.
Take for example the next code block, where I extend the DataRow object and adds a print_me method that prints the row's columns and values:
class System::Data::DataRow
def print_me
self.table.columns.each do |col|
print "#{col.ColumnName}: #{self.get_Item(col.ColumnName)}\t"
end
end
end
The print_me method goes over the table columns and prints out the column name and current value.
Now, you can loop over your dataset rows and print them with ease:
my_dataset.Tables.get_Item(0).rows.each do |row|
row.print_me
end
Now you're probably thinking "I can do that with extension methods and I don't have to leave my beloved static language". Well, you're right! But now I want to introduce you with something you can't do in pure .Net!
Ruby has this great possibility - the method_missing method. This method is called whenever the code generates a call to a method that doesn't exist. This technique is used quite widely through Ruby frameworks. For example, you can call a method like add_Shay_to_list and the method_missing method will interpret the call and add "Shay" to the list...
Now we're gonna take it and give .Net DataSets a new and powerful feature!
In the next code block I will create the possibility to access data rows directly, using them like if they were properties.
For instance, if I have a record with the value "John Doe" in the Name column, I'll be able to access it by calling my_dataset.John_Doe. As simple as that! along with the print_me method that we have declared earlier, we can call my_dataset.John_Doe.print_me in order to print John Doe's row details. Hysterical! :)
All the code I need to write in order to achieve that is:
class System::Data::DataSet
def method_missing(name, *args)
userName = name.to_s.gsub("_"," ")
result = self.tables.get_Item(0).select("Name = '#{userName}'")
if (result != nil)
return result[0]
end
end
end
(I assume here that I have a table and it has a column named Name).
That's it! I've given this powerful feature to every dataset I use in my code!
Now for the whole project code - it includes a simple dataset generation and an example of using the new and shining DataSet feature:
class System::Data::DataSet
def method_missing(name, *args)
# replace '_' with spaces
userName = name.to_s.gsub("_"," ")
# select the value from the table
result = self.tables.get_Item(0).select("Name = '#{userName}'")
if (result != nil)
return result[0]
end
end
end
class System::Data::DataRow
def print_me
self.table.columns.each do |col|
print "#{col.ColumnName}: #{self.get_Item(col.ColumnName)}\t"
end
end
end
ds = System::Data::DataSet.new
# create a table
users_table = ds.tables.add "Users"
# create columns
users_table.columns.add "Name"
users_table.columns.add "Email"
users_table.columns.add "Phone"
# fill data
users_table.rows.add("Iron Ruby","iron@ruby","03-999123")
users_table.rows.add("Iron Python","iron@python","03-812121")
users_table.rows.add("John Doe","john@doe.com","001-22323-231114")
# use the new feature in order to access records directly
ds.Iron_Ruby.print_me
ds.John_Doe.print_me
Haven't had enough? come to my session about dynamic languages and the .Net framework at the Developer Academy III event! :)
All the best,
Shay.