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> /// 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 RazorEngineHost(CodeLanguage) { DefaultBaseClass = BuildTypeName(templateType, modelType), DefaultClassName = className, DefaultNamespace = "CompiledRazorTemplates.Dynamic", GeneratedClassContext = new GeneratedClassContext( "Execute", "Write", "WriteLiteral", "WriteTo", "WriteLiteralTo", "ServiceStack.Razor2.Templating.TemplateWriter", "WriteSection") { ResolveUrlMethodName = "Href" } }; 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); }