|
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter;
using Microsoft.CSharp;
using Microsoft.CSharp.RuntimeBinder;
using Raven.Database.Linq.PrivateExtensions;
namespace Raven.Database.Linq
{
public class QueryParsingUtils
{
public static string GenerateText(TypeDeclaration type)
{
var unit = new CompilationUnit();
unit.AddChild(new Using(typeof (AbstractViewGenerator).Namespace));
unit.AddChild(new Using(typeof (Enumerable).Namespace));
unit.AddChild(new Using(typeof (int).Namespace));
unit.AddChild(new Using(typeof (LinqOnDynamic).Namespace));
unit.AddChild(type);
var output = new CSharpOutputVisitor();
unit.AcceptVisitor(output, null);
return output.Text;
}
public static VariableDeclaration GetVariableDeclaration(string query)
{
var parser = ParserFactory.CreateParser(SupportedLanguage.CSharp, new StringReader("var q = " + query));
var block = parser.ParseBlock();
if (block.Children.Count != 1)
throw new InvalidOperationException("Could not understand query: \r\n" + parser.Errors.ErrorOutput);
var declaration = block.Children[0] as LocalVariableDeclaration;
if (declaration == null)
throw new InvalidOperationException("Only local variable decleration are allowed");
if (declaration.Variables.Count != 1)
throw new InvalidOperationException("Only one variable declaration is allowed");
var variable = declaration.Variables[0];
if (variable.Initializer == null)
throw new InvalidOperationException("Variable declaration must have an initializer");
var queryExpression = (variable.Initializer as QueryExpression);
if (queryExpression == null)
throw new InvalidOperationException("Variable initializer must be a query expression");
var selectClause = queryExpression.SelectOrGroupClause as QueryExpressionSelectClause;
if (selectClause == null)
throw new InvalidOperationException("Variable initializer must be a select query expression");
var createExpression = selectClause.Projection as ObjectCreateExpression;
if (createExpression == null || createExpression.IsAnonymousType == false)
throw new InvalidOperationException(
"Variable initializer must be a select query expression returning an anonymous object");
return variable;
}
public static Type Compile(string name, string queryText)
{
var provider = new CSharpCodeProvider(new Dictionary<string, string> {{"CompilerVersion", "v4.0"}});
var results = provider.CompileAssemblyFromSource(new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = false,
IncludeDebugInformation = true,
ReferencedAssemblies =
{
typeof (AbstractViewGenerator).Assembly.Location,
typeof (NameValueCollection).Assembly.Location,
typeof (Enumerable).Assembly.Location,
typeof (Binder).Assembly.Location,
},
}, queryText);
if (results.Errors.HasErrors)
{
var sb = new StringBuilder()
.AppendLine("Source code:")
.AppendLine(queryText)
.AppendLine();
foreach (CompilerError error in results.Errors)
{
sb.AppendLine(error.ToString());
}
throw new InvalidOperationException(sb.ToString());
}
return results.CompiledAssembly.GetType(name);
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I've been a software developer since 1996 and have enjoyed C# since 2003. I have a Bachelor's degree in Computer Science and for some reason, a Master's degree in Business Administration. I currently do software development contracting/consulting.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.