private Tuple <CompilerResults, string> Compile(TypeContext context)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            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 = CompilerServicesUtility
                             .GetLoadedAssemblies()
                             .Where(a => !a.IsDynamic && File.Exists(a.Location))
                             .GroupBy(a => a.GetName().Name).Select(grp => grp.First(y => y.GetName().Version == grp.Max(x => x.GetName().Version))) // only select distinct assemblies based on FullName to avoid loading duplicate assemblies
                             .Select(a => a.Location);

            var includeAssemblies = (IncludeAssemblies() ?? Enumerable.Empty <string>());

            assemblies = assemblies.Concat(includeAssemblies)
                         .Where(a => !string.IsNullOrWhiteSpace(a))
                         .Distinct(StringComparer.InvariantCultureIgnoreCase);

            @params.ReferencedAssemblies.AddRange(assemblies.ToArray());

            string sourceCode = null;

            if (Debug)
            {
                var builder = new StringBuilder();
                using (var writer = new StringWriter(builder, CultureInfo.InvariantCulture)) {
                    _codeDomProvider.GenerateCodeFromCompileUnit(compileUnit, writer, new CodeGeneratorOptions());
                    sourceCode = builder.ToString();
                }
            }

            return(Tuple.Create(_codeDomProvider.CompileAssemblyFromDom(@params, compileUnit), sourceCode));
        }
예제 #2
0
        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.");
            }

            namespaceImports = namespaceImports ?? new HashSet <string>();
            templateType     = templateType ?? ((modelType == null) ? typeof(TemplateBase) : typeof(TemplateBase <>));

            // Create the RazorEngineHost
            var host = CreateHost(templateType, modelType, className);

            // Add any required namespace imports
            foreach (var ns in GetNamespaces(templateType, namespaceImports))
            {
                host.NamespaceImports.Add(ns);
            }

            // Gets the generator result.
            var result = GetGeneratorResult(host, template);

            // Add the dynamic model attribute if the type is an anonymous type.
            var type = result.GeneratedCode.Namespaces[0].Types[0];

            if (modelType != null && CompilerServicesUtility.IsAnonymousType(modelType))
            {
                type.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(HasDynamicModelAttribute))));
            }

            // Generate any constructors required by the base template type.
            GenerateConstructors(CompilerServicesUtility.GetConstructors(templateType), type);

            // Despatch any inspectors
            Inspect(result.GeneratedCode);

            return(result.GeneratedCode);
        }
예제 #3
0
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder == null)
            {
                throw new ArgumentNullException("binder");
            }

            var dynamicObject = Model as RazorDynamicObject;

            if (dynamicObject != null)
            {
                return(dynamicObject.TryGetMember(binder, out result));
            }

            var modelType = Model.GetType();
            var prop      = modelType.GetProperty(binder.Name);

            if (prop == null)
            {
                result = null;
                return(false);
            }

            var value = prop.GetValue(Model, null);

            if (value == null)
            {
                result = value;
                return(true);
            }

            var valueType = value.GetType();

            result = (CompilerServicesUtility.IsAnonymousType(valueType))
                         ? new RazorDynamicObject
            {
                Model = value
            }
                         : value;
            return(true);
        }
예제 #4
0
 /// <summary>
 ///     Initialises a new instance of <see cref="TypeContext" />.
 /// </summary>
 internal TypeContext()
 {
     ClassName  = CompilerServicesUtility.GenerateClassName();
     Namespaces = new HashSet <string>();
 }