{"id":1581,"date":"2011-04-06T21:24:59","date_gmt":"2011-04-06T20:24:59","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=1581"},"modified":"2022-01-23T22:26:19","modified_gmt":"2022-01-23T21:26:19","slug":"db4o-linqpad-driver-generate-code","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2011\/04\/db4o-linqpad-driver-generate-code\/","title":{"rendered":"Making of the db4o LINQPad Driver: Generate Code"},"content":{"rendered":"<div id=\"attachment_1583\" style=\"width: 310px\" class=\"wp-caption alignright\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/04\/playing-the-compiler.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1583\" class=\"size-medium wp-image-1583\" title=\"playing-the-compiler\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/04\/playing-the-compiler-300x270.png\" alt=\"Playing Compilier \" width=\"300\" height=\"270\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/04\/playing-the-compiler-300x270.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/04\/playing-the-compiler.png 600w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1583\" class=\"wp-caption-text\">Playing Compilier <\/p><\/div>\n<p>In the previous posts I showed you how to write <a href=\"https:\/\/www.gamlor.info\/?p=1543\">LINQPad drivers<\/a> and how to read the <a href=\"https:\/\/www.gamlor.info\/?p=1571\">meta data out of db4o<\/a>. This time I show the last piece for a functional driver, the code generation. Code generation is required to dynamically create the query context and entities for LINQPad.<\/p>\n<p>Side note: I\u2019ve fixed more bugs in <a href=\"https:\/\/www.gamlor.info\/files\/db4oPad.lpx\">the driver<\/a>. I\u2019ve also added the code to access meta-information. However that part doesn\u2019t work at the moment due to db4o-bugs.<\/p>\n<h2>Code Generation Basics<\/h2>\n<p>There are different ways to generate code in .NET. The low level <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.reflection.emit.aspx\">Reflection.Emit namespace<\/a> gives you basic code generation capabilities. With the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/y2k85ax6.aspx\">CodeDom-API<\/a> you can compile regular C# code at runtime. Also remember that you can use <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.linq.expressions.aspx\">LINQ-Expressions<\/a> to create delegate implementations. Of course there are numerous external libraries which help, like <a href=\"http:\/\/www.castleproject.org\/dynamicproxy\/index.html\">Castle Dynamic Proxies.<\/a><\/p>\n<p>For my LINQPad driver I\u2019m using the basic Reflection.Emit API. The first step you need to do is to create a new assembly which hosts the code:<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=CreateAssembly.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain\n    .DefineDynamicAssembly(new AssemblyName(&quot;MyDynamicAssembly&quot;),\n                            AssemblyBuilderAccess.Run);\nModuleBuilder modBuilder = assemblyBuilder.DefineDynamicModule(&quot;MyDynamicAssembly&quot;);<\/code><\/pre><\/noscript>\n<p>After that you can create any numbers of new types:<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=CreateType.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">TypeBuilder typeBuilder = modBuilder.DefineType(&quot;MyDynamicAssembly.DataType.AClass&quot;,\n                                                    TypeAttributes.Class | TypeAttributes.Public);<\/code><\/pre><\/noscript>\n<p>You can add fields, properties and methods to the created types.<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=AddingFieldsEtc.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">\/\/ Creating a field on the type\nFieldBuilder field = typeBuilder.DefineField(&quot;nameOfField&quot;, typeof (string), FieldAttributes.Private);\n\n\/\/ Adding a new property to the type\nPropertyBuilder property = typeBuilder.DefineProperty(&quot;NameOfProperty&quot;,\n                                            PropertyAttributes.HasDefault,\n                                            typeof (string), null);\n\n\/\/ A property needs the actual implementation-method. Here the a getter\nMethodBuilder getterMethod = typeBuilder.DefineMethod(&quot;get_NameOfProperty&quot;,\n                                                MethodAttributes.Public | MethodAttributes.SpecialName |\n                                                MethodAttributes.HideBySig,\n                                                typeof (string), Type.EmptyTypes);\nproperty.SetGetMethod(getterMethod);<\/code><\/pre><\/noscript>\n<p>The hardest part about is to fill the method-body. For that you generate CIL code. That\u2019s loads of fun. If you\u2019re not familiar with CIL code you maybe should at the CIL-code from existing assemblies to learn from it.<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=CILCode.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">\/\/ Hell yeah. CIL-Code-generation\nILGenerator ilGenerator = getterMethod.GetILGenerator();\nilGenerator.Emit(OpCodes.Ldarg_0); \/\/ Load this pointer\nilGenerator.Emit(OpCodes.Ldfld, field); \/\/ Load value from the field\nilGenerator.Emit(OpCodes.Ret); \/\/ Return<\/code><\/pre><\/noscript>\n<p>The last step is to create the type. This freezes the type and it can be loaded by the CLR.<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=FinalResult.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">Type finalResult = typeBuilder.CreateType();<\/code><\/pre><\/noscript>\n<p>That\u2019s it; you\u2019ve generated code at runtime. You now go crazy with it =).<\/p>\n<h2>Mixing with Expressions<\/h2>\n<p>As we\u2019ve seen generating code directly with CIL expressions is painful. A more elegant way is to compose <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.linq.expressions.aspx\">LINQ-Expressions<\/a> at runtime and the compile these expressions. You actually can generate a method body with expressions. The LambdaExpression has a compile method which accepts a method builder (since .NET 4.0) . That makes it much easier to implement the method body:<\/p>\n<script src=\"https:\/\/gist.github.com\/906354.js?file=WithExpressions.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">\/\/ Expressions are nicer way to generate code\nvar call = Expression.Constant(&quot;hello world&quot;);\nvar lambda = Expression.Lambda(typeof(Func&lt;string&gt;),\n\tcall, new ParameterExpression[0]);\nlambda.CompileToMethod(getterMethod);<\/code><\/pre><\/noscript>\n<p>However there\u2019s a huge limitation to this. You can only generate code for static method right now. =\/<\/p>\n<h2>Generating Code for LINQPad<\/h2>\n<p>LINQPad driver needs two things. The first is types for the entities which you want to query. In my driver I generate classes for all stored types in db4o. The second thing is the query context. The query context should have a structure like this:<\/p>\n<script src=\"https:\/\/gist.github.com\/906397.js?file=ContextCreatedByDriver.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">class ContextCreatedByDriver{    \n\n     public IQueryable&lt;TheType&gt; TheType\n     {\n          get{\/* your implementation *\/}\n     }\n\n}<\/code><\/pre><\/noscript>\n<p>LINQPad takes that query-context and creates a subclass of it. That subclass contains an enty-method which contains the code typed into LINQPad. That way your query simply can access all the properties of your database context. Of course you can add any method or property to your context and can make it accessible from LINQPad.<\/p>\n<script src=\"https:\/\/gist.github.com\/906397.js?file=QueryExecutor.cs\"><\/script><noscript><pre><code class=\"language-c# c#\">class QueryExecutor : ContextCreatedByDriver{\n    \n\n     public void LinqPadQueryMain(){\n\t\t\/\/ the query the user writes\n\t\t(from t in TheType\n\t\tselec t).Dump();  \/\/ And the Dump\n\t }\n}<\/code><\/pre><\/noscript>\n<p>Conclusion<\/p>\n<p>Well know we know all important steps to write a LINQPad driver, from the LINQPad API to the code generation. Have fun writing your own driver \ud83d\ude09 or using an existing driver.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous posts I showed you how to write LINQPad drivers and how to read the meta data out of db4o. This time I show the last piece for&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[126,150],"tags":[21,100,214],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1581"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=1581"}],"version-history":[{"count":6,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1581\/revisions"}],"predecessor-version":[{"id":3925,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1581\/revisions\/3925"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=1581"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=1581"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=1581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}