public override bool TryGetMember(GetMemberBinder binder, out object result) { var dynamicObject = Model as RazorDynamicObject; if (dynamicObject != null) { return(dynamicObject.TryGetMember(binder, out result)); } Type modelType = Model.GetType(); var prop = modelType.GetProperty(binder.Name); if (prop == null) { result = null; return(false); } object value = prop.GetValue(Model, null); if (value == null) { result = value; return(true); } Type valueType = value.GetType(); result = (CompilerServices.IsAnonymousType(valueType)) ? new RazorDynamicObject { Model = value } : value; return(true); }
/// <summary> /// Creates the compile results for the specified <see cref="TypeContext"/>. /// </summary> /// <param name="context">The type context.</param> /// <returns>The compiler results.</returns> private CompilerResults Compile(TypeContext context) { var compileUnit = GetCodeCompileUnit( context.ClassName, context.TemplateContent, context.Namespaces, context.TemplateType, context.ModelType); var @params = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false, IncludeDebugInformation = false, CompilerOptions = "/target:library /optimize", }; var assemblies = CompilerServices .GetLoadedAssemblies() .Where(a => !a.IsDynamic) .Select(a => a.Location) .ToArray(); @params.ReferencedAssemblies.AddRange(assemblies); if (Env.IsMono) { for (var i = @params.ReferencedAssemblies.Count - 1; i >= 0; i--) { var assembly = @params.ReferencedAssemblies[i]; foreach (var filterAssembly in DuplicatedAssmebliesInMono) { if (assembly.Contains(filterAssembly)) { @params.ReferencedAssemblies.RemoveAt(i); } } } } return(CodeDomProvider.CompileAssemblyFromDom(@params, compileUnit)); }
/// <summary> /// Builds a type name for the specified template type and model type. /// </summary> /// <param name="templateType">The template type.</param> /// <param name="modelType">The model type.</param> /// <returns>The string type name (including namespace).</returns> public virtual string BuildTypeName(Type templateType, Type modelType) { if (templateType == null) { throw new ArgumentNullException("templateType"); } if (!templateType.IsGenericTypeDefinition && !templateType.IsGenericType) { return(templateType.FullName); } if (modelType == null) { throw new ArgumentException("The template type is a generic defintion, and no model type has been supplied."); } bool @dynamic = CompilerServices.IsDynamicType(modelType); Type genericType = templateType.MakeGenericType(modelType); return(BuildTypeNameInternal(genericType, @dynamic)); }
public Type Compile() { Type forceLoadOfRuntimeBinder = typeof(Microsoft.CSharp.RuntimeBinder.Binder); if (forceLoadOfRuntimeBinder == null) { log.Warn("Force load of .NET 4.0+ RuntimeBinder in Microsoft.CSharp.dll"); } var razorResults = Generate(); var @params = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false, IncludeDebugInformation = false, CompilerOptions = "/target:library /optimize", TempFiles = { KeepFiles = true } }; var assemblies = CompilerServices .GetLoadedAssemblies() .Where(a => !a.IsDynamic) .Select(a => a.Location) .ToArray(); @params.ReferencedAssemblies.AddRange(assemblies); //Compile the code var results = _codeDomProvider.CompileAssemblyFromDom(@params, razorResults.GeneratedCode); OnCodeCompletion(); var tempFilesMarkedForDeletion = new TempFileCollection(null); @params.TempFiles .OfType <string>() .ForEach(file => tempFilesMarkedForDeletion.AddFile(file, false)); using (tempFilesMarkedForDeletion) { if (results.Errors != null && results.Errors.HasErrors) { //check if source file exists, read it. //HttpCompileException is sealed by MS. So, we'll //just add a property instead of inheriting from it. var sourceFile = results.Errors .OfType <CompilerError>() .First(ce => !ce.IsWarning) .FileName; var sourceCode = ""; if (!string.IsNullOrEmpty(sourceFile) && System.IO.File.Exists(sourceFile)) { sourceCode = System.IO.File.ReadAllText(sourceFile); } else { foreach (string tempFile in @params.TempFiles) { if (tempFile.EndsWith(".cs")) { sourceCode = System.IO.File.ReadAllText(tempFile); } } } throw new HttpCompileException(results, sourceCode); } #if DEBUG foreach (string tempFile in @params.TempFiles) { if (tempFile.EndsWith(".cs")) { var sourceCode = System.IO.File.ReadAllText(tempFile); //sourceCode.Print(); } } #endif return(results.CompiledAssembly.GetTypes().First()); } }
public Type Compile() { Type forceLoadOfRuntimeBinder = typeof(Microsoft.CSharp.RuntimeBinder.Binder); if (forceLoadOfRuntimeBinder == null) { log.Warn("Force load of .NET 4.0+ RuntimeBinder in Microsoft.CSharp.dll"); } var razorResults = Generate(); var @params = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false, IncludeDebugInformation = IncludeDebugInformation, CompilerOptions = "/target:library" + (IncludeDebugInformation ? "" : " /optimize"), TempFiles = { KeepFiles = true } }; var assemblies = CompilerServices .GetLoadedAssemblies() .Where(a => !a.IsDynamic); if (Env.IsMono) { //workaround mono not handling duplicate dll references (i.e. in GAC) var uniqueNames = new HashSet <string>(); assemblies = assemblies.Where(x => { var id = x.GetName().Name; if (string.IsNullOrEmpty(id)) { return(true); } if (uniqueNames.Contains(id)) { return(false); } if (!id.Contains("<")) { uniqueNames.Add(x.GetName().Name); } return(true); }); } var assemblyNames = assemblies .Select(a => a.Location) .ToArray(); @params.ReferencedAssemblies.AddRange(assemblyNames); if (CompileFilter != null) { CompileFilter(@params); } //Compile the code var results = _codeDomProvider.CompileAssemblyFromDom(@params, razorResults.GeneratedCode); var tempFilesMarkedForDeletion = new TempFileCollection(null); foreach (var file in @params.TempFiles.OfType <string>()) { tempFilesMarkedForDeletion.AddFile(file, false); } using (tempFilesMarkedForDeletion) { if (results.Errors != null && results.Errors.HasErrors) { //check if source file exists, read it. //HttpCompileException is sealed by MS. So, we'll //just add a property instead of inheriting from it. var sourceFile = results.Errors .OfType <CompilerError>() .First(ce => !ce.IsWarning) .FileName; var sourceCode = ""; if (!string.IsNullOrEmpty(sourceFile) && System.IO.File.Exists(sourceFile)) { sourceCode = System.IO.File.ReadAllText(sourceFile); } else { foreach (string tempFile in @params.TempFiles) { if (tempFile.EndsWith(".cs")) { sourceCode = System.IO.File.ReadAllText(tempFile); } } } throw new HttpCompileException(results, sourceCode); } #if DEBUG foreach (string tempFile in @params.TempFiles) { if (tempFile.EndsWith(".cs")) { var sourceCode = System.IO.File.ReadAllText(tempFile); //sourceCode.Print(); } } #endif return(results.CompiledAssembly.GetTypes().First()); } }
/// <summary> /// Gets the code compile unit used to compile a type. /// </summary> /// <param name="className">The class name.</param> /// <param name="template">The template to compile.</param> /// <param name="namespaceImports">The set of namespace imports.</param> /// <param name="templateType">The template type.</param> /// <param name="modelType">The model type.</param> /// <returns>A <see cref="CodeCompileUnit"/> used to compile a type.</returns> public CodeCompileUnit GetCodeCompileUnit(string className, string template, ISet <string> namespaceImports, Type templateType, Type modelType) { if (string.IsNullOrEmpty(className)) { throw new ArgumentException("Class name is required."); } if (string.IsNullOrEmpty(template)) { throw new ArgumentException("Template is required."); } templateType = templateType ?? ((modelType == null) ? typeof(TemplateBase) : typeof(TemplateBase <>)); var host = new MvcWebPageRazorHost(CodeLanguage, () => MarkupParser) { DefaultBaseClass = BuildTypeName(templateType, modelType), DefaultClassName = className, DefaultNamespace = "CompiledRazorTemplates.Dynamic", GeneratedClassContext = new GeneratedClassContext( "Execute", "Write", "WriteLiteral", "WriteTo", "WriteLiteralTo", "ServiceStack.Razor.Templating.TemplateWriter", "WriteSection") }; var templateNamespaces = templateType.GetCustomAttributes(typeof(RequireNamespacesAttribute), true) .Cast <RequireNamespacesAttribute>() .SelectMany(att => att.Namespaces); foreach (string ns in templateNamespaces) { namespaceImports.Add(ns); } foreach (string @namespace in namespaceImports) { host.NamespaceImports.Add(@namespace); } var engine = new RazorTemplateEngine(host); GeneratorResults result; using (var reader = new StringReader(template)) { result = engine.GenerateCode(reader); } var type = result.GeneratedCode.Namespaces[0].Types[0]; if (modelType != null) { if (CompilerServices.IsAnonymousType(modelType)) { type.CustomAttributes.Add(new CodeAttributeDeclaration( new CodeTypeReference(typeof(HasDynamicModelAttribute)))); } } GenerateConstructors(CompilerServices.GetConstructors(templateType), type); var statement = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Clear"); foreach (CodeTypeMember member in type.Members) { if (member.Name.Equals("Execute")) { ((CodeMemberMethod)member).Statements.Insert(0, new CodeExpressionStatement(statement)); break; } } return(result.GeneratedCode); }
/// <summary> /// Creates the compile results for the specified <see cref="TypeContext"/>. /// </summary> /// <param name="context">The type context.</param> /// <returns>The compiler results.</returns> private CompilerResults Compile(TypeContext context) { var compileUnit = GetCodeCompileUnit( context.ClassName, context.TemplateContent, context.Namespaces, context.TemplateType, context.ModelType); var @params = new CompilerParameters { GenerateInMemory = true, GenerateExecutable = false, IncludeDebugInformation = false, CompilerOptions = "/target:library /optimize", TempFiles = { KeepFiles = true } }; var assemblies = CompilerServices .GetLoadedAssemblies() .Where(a => !a.IsDynamic) .Select(a => a.Location) .ToArray(); @params.ReferencedAssemblies.AddRange(assemblies); if (Env.IsMono) { for (var i = @params.ReferencedAssemblies.Count - 1; i >= 0; i--) { var assembly = @params.ReferencedAssemblies[i]; foreach (var filterAssembly in DuplicatedAssmebliesInMono) { if (assembly.Contains(filterAssembly)) { @params.ReferencedAssemblies.RemoveAt(i); } } } } var results = CodeDomProvider.CompileAssemblyFromDom(@params, compileUnit); //Tricky: Don't forget to cleanup. // Simply setting KeepFiles = false and then calling // dispose on the parent TempFilesCollection won't // clean up. So, create a new collection and // explicitly mark the files for deletion. var tempFilesMarkedForDeletion = new TempFileCollection(null); @params.TempFiles .OfType <string>() .ForEach(file => tempFilesMarkedForDeletion.AddFile(file, false)); using ( tempFilesMarkedForDeletion ) { if (results.Errors != null && results.Errors.HasErrors) { throw new TemplateCompilationException(results); } return(results); } }
/// <summary> /// Initialises a new instance of <see cref="TypeContext"/>. /// </summary> public TypeContext() { ClassName = CompilerServices.GenerateClassName(); Namespaces = new HashSet <string>(); }