I was glad to see dynamic features available in C# back when version 4 came out (in 2010, if memory serves me right…). But, why did I care?
Back in my old days, prior to start working with .NET, I was working heavily on Visual FoxPro projects. FoxPro was a weakly-typed, dynamic, object-oriented language, which also featured it’s own SQL (Structured Query Language), and a fast local database. Now, what does all mean?
I could define a class (say, “User”), instantiate it, and call methods on it (such as, “SayHello”):
SQL (Structured Query Language)
FoxPro allowed me write code like this:
SELECT Address, PhoneNumber FROM C:\DB\CUSTOMERS.DBF WHRE Id = 1 INTO C:\TEMP\TEMP_CUSTOMERS.DBF
No need to create a connection to a database: I could simply query some data off of a local file, and even dump into to another local file.
I could also create an object out of the current row off my query results, with properties matching the columns in the table (think Entity Framework reading data off a database and pushing into objects for you):
SCATTER NAME customer customer.Address customer.PhoneNumber
We could assign an integer to a variable in one line, and then assign a string to it in another, and FoxPro was happy:
myVariable = 1234 myVariable = “Woohoo!!”
Nope, that wasn’t necessarily a good thing, as people definitely abused that possibility. However, there were scenarios where it came in handy.
I could do the following:
1. Put the name of a class to instantiate and the name of a method to call in a string (both could be coming from a database):
className = “User” methodName = “SayHello"
2. Merge those variables to another string variable representing lines of code:
text to someVariable texmerge noshow instance = CreateObject(“<< className >>”) result = loInstance.<< methodName >>() MessageBox(result) endtext
3. Execute the code contained in that string variable like so:
Putting it all together
So it was common to see code somewhat like this:
SELECT ClassName, MethodName FROM WhateverTable WHERE Module == “Hello World” SCATTER NAME behavior text to someVariable texmerge noshow instance = CreateObject(“<< behavior.className >>”) result = loInstance.<< behavior.methodName >>() MessageBox(result) result = 1234 MessageBox(result) endtext &someVariable
In reality, some FoxPro projects store entire modules created based off dynamic code like the one above, stored in databases.
Rewriting FoxPro “dynamic” software in .NET
I’ve worked in projects where the client wanted those FoxPro “dynamic” applications rewritten in .NET. I’ve been told many times that “our application is 100% dynamic; everything can be configured by the end-user”. I’ve even blogged about that. In the end, not everything was dynamic, but there were dynamic parts, indeed:
- Extend the system by adding new tables (but always based off existing ones);
- Add columns to existing tables
- Define what columns show on the grid
- Define how columns, rows, and cells where displayed (background color, enable/disable, header, etc.)
- Create CRUD screens for those columns they added;
- Create reports using those new columns;
- Create “expressions” that are evaluated in several situations (enabling/disabling a field, setting the default value of a field based off other fields, etc.). For example, maybe the default value for a new “Total” column in a table should be the result of the following expression (imagine that both Price and Quantity are also columns added by the user):
- context.Product.Price * context.Item.Quantity
Reproducing some of those pieces in C# wasn’t exactly easy back then, so this posts answers why I cared about the dynamic features introduced in C# several years ago.
In the next post I’ll go over what I did before the dynamic features of C# came around.