Generating Data Access Assemblies with IronRuby Rob Rowe Twitter: @rippinrobr Blog: rob-rowe.blogspot.com Why? • Make tedious changes easier and quicker • Create code based off of data specs from outside sources • Wanted to learn Ruby • Used IronRuby to access to .NET libraries such as System.Reflection.Emit • Generate a DLL without compilation What is IronRuby? • An implementation of Ruby 1.8.x • Built on top of .NET’s Dynamic Language Runtime • Allows IronRuby to access .NET objects such as System.Reflection or any other .NET library • Easy to ‘load’ .NET libraries Overview Consuming Application – ASP.NET MVC 2 Generated Code – Models DLL and C# Domain/Service layer Field Definitions Tables Creating a .NET Assembly 1. 2. 3. 4. 5. Establish Assembly characteristics Create the new Assembly Define the Module Create the Class Create the Properties a. b. c. d. Create the backing field Create the Property Create Getter Create Setter 6. Save the Assembly 1. Establish Assembly Characteristics • Create an instance of the System.Reflection.AssemblyName class • Set Version • Set Name • Can set CultureInfo, Crypto KeyPair among as well as other settings 2. Create the new Assembly • Creates the assembly in memory • The first parameter is the AssemblyName object from step 1. • Second parameter sets the permissions for the assembly. Here we can run it and save it to the file system. • Returns an AssemblyBuilder Object. Used to create the module for the assembly. 3. Define the Module • Each .NET assembly must have at least one module • ‘Container’ for classes, interfaces, etc. • Parameters: 1. Name of the module 2. Name of the DLL 3. false – so no symbols are created 4. Create the Class • @mod_builder is the object returned when we created the module. Creates the class ‘under’ the module • First parameter is fully qualified name of the class • Second parameter is used to set public, static, etc. • Returned TypeBuilder object is used to create the class’s fields and properties. 5a. Create Fields • • • • Must create a field for each property Creates a private field used by the getter/setters Uses the class’s TypeBuilder object Parameters ▫ Defines the name ▫ CLR Type ▫ Sets Access level 5b. Create Properties • Creates the Property’s TypeObject used for getter/setters • Parameters: ▫ ▫ ▫ ▫ Property Name Says there’s a default value for this property The CLR Type Since there are no parameters for our properties we pass in null 5c. Create Getter – Prep Work • Creates the Get method TypeObject • DefineMethod’s parameters ▫ ▫ ▫ ▫ Name of the method Attributes for the method Return type (CLR type) Parameters to the method – none for getter • GetILGenerator - creates the object that is used to create the IL code 5c. Create Getter – Method Body • OpCodes.Ldarg_0 – loads the first argument on the stack which is ‘this’ in our case. • OpCodes.Ldfld – pushes the value of the private field onto the stack. • OpCodes.Ret – the returns the last item on the evaluation stack, the value of the private field. 5d. Create Setter – Parameters • Constructs the Type array needed for the setter’s method parameters • The type added to the list is the CLR type of the property • Need to use a generic list to create the necessary CLR array • Use List<T>’s ToArray method to get around CLR array type issues 5d. Create Setter – Method Body • OpCodes.Ldarg_0 – loads the first argument on the stack which is ‘this’ in our case. • OpCodes.Ldarg_1 - loads the setter parameter onto the stack • OpCodes.Stfld – sets the value of private_field to the value of the item popped from the stack. • OpCodes.Ret – adds the return statement. 5e. Finalizing Property Creation • Need to associate the getter and setter with our new property • Use the property TypeBuilder to associate the two method’s TypeBuilder objects with the IL we just created 6. Saving the Assembly • The assembly is saved to the file system by using the AssemblyBuilder object’s Save method • Once it has been saved we can use our new Models DLL like any other assembly. Resources/Contact Info • • • • Robert.rowe@duke.edu Twitter: @rippinrobr Blog: rob-rowe@blogspot.com Code: https://bitbucket.org/robrowe/ironrubyassembl ybuilder • Books: IronRuby Unleashed, Programming Ruby (AKA The Pickaxe Book)