Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

changed code generation to use CodeDom

  • Loading branch information...
commit 308d1db823b1920203f8680e576ab319f0f6cdc6 1 parent f83e9bd
Grant Pexsa authored
Showing with 174 additions and 74 deletions.
  1. +174 −74 utility/FluentCassandra.LinqPad/SchemaBuilder.cs
View
248 utility/FluentCassandra.LinqPad/SchemaBuilder.cs
@@ -1,4 +1,5 @@
using System;
+using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
@@ -13,93 +14,192 @@ namespace FluentCassandra.LinqPad
{
internal class SchemaBuilder
{
- internal static List<ExplorerItem> GetSchemaAndBuildAssembly(CassandraConnectionInfo info, string driverFolder, AssemblyName name, ref string nameSpace, ref string typeName)
- {
- var context = info.CreateContext();
- var keyspace = context.Keyspace;
+ internal static List<ExplorerItem> GetSchemaAndBuildAssembly(CassandraConnectionInfo info, string driverFolder, AssemblyName name, ref string nameSpace, ref string typeName)
+ {
+ var context = info.CreateContext();
+ var keyspace = context.Keyspace;
- var def = keyspace.GetSchema();
- var code = GenerateCode(def, nameSpace, typeName);
- var schema = GetSchema(def);
+ var def = keyspace.GetSchema();
- // Compile the code into the assembly, using the assembly name provided:
- BuildAssembly(code, driverFolder, name);
+ //var code = GenerateCode(def, nameSpace, typeName);
+ var schema = GetSchema(def);
- return schema;
- }
+ CodeCompileUnit targetUnit = new CodeCompileUnit();
+ CodeNamespace codeNamespace = new CodeNamespace(nameSpace);
+ codeNamespace.Imports.Add(new CodeNamespaceImport("System"));
+ codeNamespace.Imports.Add(new CodeNamespaceImport("System.Numerics"));
+ codeNamespace.Imports.Add(new CodeNamespaceImport("System.Linq"));
+ codeNamespace.Imports.Add(new CodeNamespaceImport("FluentCassandra"));
+ codeNamespace.Imports.Add(new CodeNamespaceImport("FluentCassandra.Connections"));
+ codeNamespace.Imports.Add(new CodeNamespaceImport("FluentCassandra.Types"));
+
+ CodeTypeDeclaration contextClass = new CodeTypeDeclaration(typeName);
+ contextClass.IsClass = true;
+ contextClass.TypeAttributes = TypeAttributes.Public;
+ contextClass.BaseTypes.Add(typeof (IDisposable));
- private static string GenerateCode(CassandraKeyspaceSchema schema, string nameSpace, string typeName)
- {
- var code = new StringBuilder();
+ #region Constructor
- code.AppendLine(@"using System;
-using System.Numerics;
-using System.Linq;
-using FluentCassandra;
-using FluentCassandra.Connections;
-using FluentCassandra.Types;");
- code.Append(@"namespace " + nameSpace + @" {
- public class " + typeName + @" : IDisposable
- {
- public FluentCassandra.CassandraContext Context { get; private set; }
- public FluentCassandra.CassandraSession Session { get; private set; }
+ CodeConstructor codeConstructor = new CodeConstructor();
+ codeConstructor.Attributes = MemberAttributes.Public;
+ codeConstructor.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(CassandraContext)), "context"));
+ codeConstructor.Statements.Add(
+ new CodeSnippetStatement(
+ @"if (context == null) throw new ArgumentNullException(""context"", ""context is null.""); _context_9e94d563_59a5_4e31_8919_fd15298559d9 = context; _session_9e94d563_59a5_4e31_8919_fd15298559d9 = new CassandraSession(Context.ConnectionBuilder);"));
- public " + typeName + @"(FluentCassandra.CassandraContext context)
- {
- if (context == null)
- throw new ArgumentNullException(""context"", ""context is null."");
+ contextClass.Members.Add(codeConstructor);
- Context = context;
- Session = new CassandraSession(Context.ConnectionBuilder);
- }
+ #endregion
- public void Dispose()
- {
- if (Session != null)
- Session.Dispose();
+ #region IDisposable
- if (Context != null && !Context.WasDisposed)
- Context.Dispose();
- }
-");
- foreach (var familyDef in schema.ColumnFamilies)
- {
- var familyName = familyDef.FamilyName;
- code.AppendLine(@"
- private FluentCassandra.CassandraColumnFamily _" + familyName + @";
- public FluentCassandra.CassandraColumnFamily " + familyName + @" { get {
- if (_" + familyName + @" == null)
- _" + familyName + @" = Context.GetColumnFamily(""" + familyName + @""");
-
- return _" + familyName + @";
- } }");
- }
- code.AppendLine(@"
- }
-}");
+ CodeMemberMethod disposeMethod = new CodeMemberMethod();
+ disposeMethod.Attributes = MemberAttributes.Public;
+ disposeMethod.Name = "Dispose";
+ disposeMethod.ReturnType = new CodeTypeReference(typeof(void));
+ disposeMethod.Statements.Add(new CodeSnippetStatement(@"if (Session != null) Session.Dispose(); if (Context != null && !Context.WasDisposed) Context.Dispose();"));
- return code.ToString();
- }
+ contextClass.Members.Add(disposeMethod);
- private static void BuildAssembly(string code, string driverFolder, AssemblyName name)
- {
- var fluentCassandraDll = Path.Combine(driverFolder, "FluentCassandra.dll");
+ #endregion
- // Use the CSharpCodeProvider to compile the generated code
- CompilerResults results;
- using (var codeProvider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } }))
- {
- var options = new CompilerParameters(
- new[] { "System.dll", "System.Core.dll", "System.Numerics.dll", "System.Web.dll", "Microsoft.CSharp.dll", fluentCassandraDll },
- name.CodeBase,
- true);
- results = codeProvider.CompileAssemblyFromSource(options, code);
- }
+ #region CreateSessionProperty
+
+ CreatePropertyWithBackingField(contextClass, typeof(CassandraSession), "Session");
+
+ #endregion
+
+ #region CreateContextProperty
+
+ CreatePropertyWithBackingField(contextClass, typeof(CassandraContext), "Context");
+
+ #endregion
+
+ #region Create Column Family Accessors
+ foreach (CassandraColumnFamilySchema cassandraColumnFamilySchema in def.ColumnFamilies)
+ {
+ //create property accessor
+
+ if (cassandraColumnFamilySchema.Columns.Count >= 1)
+ {
+ //generate a type based on the static column family schema
+ CodeTypeDeclaration generatedClass = new CodeTypeDeclaration(cassandraColumnFamilySchema.FamilyName);
+ generatedClass.IsClass = true;
+ generatedClass.TypeAttributes = TypeAttributes.Public;
+
+ //add properties based on schema
+ foreach (CassandraColumnSchema column in cassandraColumnFamilySchema.Columns)
+ {
+ CodeMemberField newProperty = new CodeMemberField();
+ newProperty.Attributes = MemberAttributes.Public;
+ newProperty.Name = column.Name;
+ if(column.ValueType == CassandraType.UTF8Type)
+ {
+ newProperty.Type = new CodeTypeReference(typeof(string));
+ }
+
+ generatedClass.Members.Add(newProperty);
+ }
+
+ codeNamespace.Types.Add(generatedClass);
+
+
+ }
+
+ CodeMemberField field = new CodeMemberField();
+ field.Attributes = MemberAttributes.Private;
+
+ field.Type = new CodeTypeReference(typeof(CassandraColumnFamily));
+ field.Name = "_" + cassandraColumnFamilySchema.FamilyName.ToLower();
+
+ contextClass.Members.Add(field);
+
+ string statementTemplate = @"if (_{0} == null) _{0} = Context.GetColumnFamily(""{1}""); return _{0};";
+
+ CodeMemberProperty property = new CodeMemberProperty();
+ property.Attributes = MemberAttributes.Public;
+ property.Type = new CodeTypeReference(typeof(CassandraColumnFamily));
+ property.HasGet = true;
+ property.GetStatements.Add(new CodeSnippetStatement(string.Format(statementTemplate, cassandraColumnFamilySchema.FamilyName.ToLower(), cassandraColumnFamilySchema.FamilyName)));
+ property.HasSet = false;
+ property.Name = cassandraColumnFamilySchema.FamilyName;
+
+ contextClass.Members.Add(property);
+
+ //create a type for each static column family
+
+ }
+ #endregion
+
+ codeNamespace.Types.Add(contextClass);
+ targetUnit.Namespaces.Add(codeNamespace);
+
+ //compile
+ CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
+ CodeGeneratorOptions options = new CodeGeneratorOptions();
+
+
+ options.BracingStyle = "C";
+
+ CompilerParameters parameters = new CompilerParameters();
+
+ provider.CompileAssemblyFromDom(parameters, targetUnit);
+
+ using (StreamWriter sourceWriter = new StreamWriter(@"C:\temp\GeneratedCode.cs"))
+ {
+ provider.GenerateCodeFromCompileUnit(targetUnit, sourceWriter, options);
+ }
+
+
+
+ // Compile the code into the assembly, using the assembly name provided:
+ BuildAssembly(targetUnit, driverFolder, name);
+
+ return schema;
+ }
+
+ private static void CreatePropertyWithBackingField(CodeTypeDeclaration contextClass, Type typeParameter, string propertyName)
+ {
+ string backingFieldName = propertyName.ToLower() + "_9e94d563_59a5_4e31_8919_fd15298559d9";
+
+ CodeMemberField field = new CodeMemberField();
+ field.Attributes = MemberAttributes.Private;
+
+ field.Type = new CodeTypeReference(typeParameter);
+ field.Name = "_" + backingFieldName;
+
+
+ CodeMemberProperty property = new CodeMemberProperty();
+ property.Type = new CodeTypeReference(typeParameter);
+ property.HasGet = true;
+ property.HasSet = false;
+ property.Name = propertyName;
+ property.GetStatements.Add(new CodeSnippetStatement(" return _" + backingFieldName + ";"));
+
+ contextClass.Members.Add(field);
+ contextClass.Members.Add(property);
+ }
+
+ private static void BuildAssembly(CodeCompileUnit code, string driverFolder, AssemblyName name)
+ {
+ var fluentCassandraDll = Path.Combine(driverFolder, "FluentCassandra.dll");
+
+ // Use the CSharpCodeProvider to compile the generated code
+ CompilerResults results;
+ using (var codeProvider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } }))
+ {
+ var options = new CompilerParameters(
+ new[] { "System.dll", "System.Core.dll", "System.Numerics.dll", "System.Web.dll", "Microsoft.CSharp.dll", fluentCassandraDll },
+ name.CodeBase,
+ true);
+ results = codeProvider.CompileAssemblyFromDom(options, code);
+ }
+
+ if (results.Errors.Count > 0)
+ throw new Exception
+ ("Cannot compile typed context: " + results.Errors[0].ErrorText + " (line " + results.Errors[0].Line + ")");
+ }
- if (results.Errors.Count > 0)
- throw new Exception
- ("Cannot compile typed context: " + results.Errors[0].ErrorText + " (line " + results.Errors[0].Line + ")");
- }
private static List<ExplorerItem> GetSchema(CassandraKeyspaceSchema schema)
{
Please sign in to comment.
Something went wrong with that request. Please try again.