private static Assembly Compile(String outputAssembly, IEnumerable<String> references, CodeDomProvider provider, CompilerErrorCollection errors, Template tmp) { //String key = outputAssembly; //if (String.IsNullOrEmpty(key)) key = Hash(String.Join(Environment.NewLine, sources)); var sb = new StringBuilder(); foreach (var item in tmp.Templates) { if (sb.Length > 0) sb.AppendLine(); sb.Append(item.Source); } String key = Hash(sb.ToString()); Assembly assembly = null; if (asmCache.TryGetValue(key, out assembly)) return assembly; lock (asmCache) { if (asmCache.TryGetValue(key, out assembly)) return assembly; foreach (var str in references) { try { if (!String.IsNullOrEmpty(str) && File.Exists(str)) Assembly.LoadFrom(str); } catch { } } assembly = CompileInternal(outputAssembly, references, provider, errors, tmp); if (assembly != null) asmCache.Add(key, assembly); return assembly; } }
/// <summary>根据名称和模版创建模版实例,带缓存,避免重复编译</summary> /// <param name="templates">模版集合</param> /// <returns></returns> public static Template Create(IDictionary<String, String> templates) { if (templates == null || templates.Count < 1) throw new ArgumentNullException("templates"); // 计算hash StringBuilder sb = new StringBuilder(); foreach (KeyValuePair<String, String> item in templates) { sb.Append(Hash(item.Key)); sb.Append(Hash(item.Value)); } String hash = Hash(sb.ToString()); return cache.GetItem<IDictionary<String, String>>(hash, templates, delegate(String key, IDictionary<String, String> contents) { Template entity = new Template(); foreach (KeyValuePair<String, String> item in contents) { entity.AddTemplateItem(item.Key, item.Value); } //entity.Process(); //entity.Compile(); return entity; }); }
private static Assembly Compile(String outputAssembly, IEnumerable <String> references, CodeDomProvider provider, CompilerErrorCollection errors, Template tmp) { //String key = outputAssembly; //if (String.IsNullOrEmpty(key)) key = Hash(String.Join(Environment.NewLine, sources)); var sb = new StringBuilder(); foreach (var item in tmp.Templates) { if (item.Included) { continue; } if (sb.Length > 0) { sb.AppendLine(); } sb.Append(item.Source); } var key = Hash(sb.ToString()); Assembly assembly = null; if (asmCache.TryGetValue(key, out assembly)) { return(assembly); } lock (asmCache) { if (asmCache.TryGetValue(key, out assembly)) { return(assembly); } foreach (var str in references) { try { if (!String.IsNullOrEmpty(str) && File.Exists(str)) { Assembly.LoadFrom(str); } } catch { } } assembly = CompileInternal(outputAssembly, references, provider, errors, tmp); if (assembly != null) { asmCache.Add(key, assembly); } return(assembly); } }
private static Assembly CompileInternal(String outputAssembly, IEnumerable<String> references, CodeDomProvider provider, CompilerErrorCollection Errors, Template tmp) { var options = new CompilerParameters(); foreach (var str in references) { options.ReferencedAssemblies.Add(str); } options.WarningLevel = 4; CompilerResults results = null; if (Debug) { #region 调试状态,把生成的类文件和最终dll输出到XTemp目录下 var tempPath = XTrace.TempPath; //if (!String.IsNullOrEmpty(outputAssembly)) tempPath = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(outputAssembly)); if (!String.IsNullOrEmpty(outputAssembly) && !outputAssembly.Equals(".dll")) tempPath = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(outputAssembly)); if (!String.IsNullOrEmpty(tempPath) && !Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath); var files = new List<String>(); foreach (var item in tmp.Templates) { if (item.Included) continue; String name = item.Name.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) ? item.Name : item.ClassName; // 猜测后缀 Int32 p = name.LastIndexOf("_"); if (p > 0 && name.Length - p <= 5) name = name.Substring(0, p) + "." + name.Substring(p + 1, name.Length - p - 1); else if (!name.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)) name += ".cs"; name = Path.Combine(tempPath, name); File.WriteAllText(name, item.Source, Encoding.UTF8); files.Add(name); } #endregion if (!String.IsNullOrEmpty(outputAssembly) && !outputAssembly.Equals(".dll")) { options.TempFiles = new TempFileCollection(tempPath, false); options.OutputAssembly = Path.Combine(tempPath, outputAssembly); options.GenerateInMemory = true; options.IncludeDebugInformation = true; } results = provider.CompileAssemblyFromFile(options, files.ToArray()); } else { List<String> sources = new List<String>(); foreach (var item in tmp.Templates) { sources.Add(item.Source); } options.GenerateInMemory = true; results = provider.CompileAssemblyFromSource(options, sources.ToArray()); } #region 编译错误处理 if (results.Errors.Count > 0) { Errors.AddRange(results.Errors); var sb = new StringBuilder(); CompilerError err = null; foreach (CompilerError error in results.Errors) { error.ErrorText = error.ErrorText; //if (String.IsNullOrEmpty(error.FileName)) error.FileName = inputFile; if (!error.IsWarning) { String msg = error.ToString(); if (sb.Length < 1) { String code = null; // 屏蔽因为计算错误行而导致的二次错误 try { code = tmp.FindBlockCode(error.FileName, error.Line); } catch { } if (code != null) { msg += Environment.NewLine; msg += code; } err = error; } else sb.AppendLine(); sb.Append(msg); } } if (sb.Length > 0) { TemplateException ex = new TemplateException(sb.ToString()); ex.Error = err; throw ex; } } else { try { options.TempFiles.Delete(); } catch { } } #endregion if (!results.Errors.HasErrors) { try { return results.CompiledAssembly; } catch { } } return null; }
private static Assembly CompileInternal(String outputAssembly, IEnumerable <String> references, CodeDomProvider provider, CompilerErrorCollection Errors, Template tmp) { var options = new CompilerParameters(); foreach (var str in references) { options.ReferencedAssemblies.Add(str); } options.WarningLevel = 4; CompilerResults results = null; if (Debug) { //var sb = new StringBuilder(); #region 调试状态,把生成的类文件和最终dll输出到XTemp目录下 var tempPath = XTrace.TempPath.GetFullPath().EnsureDirectory(false); //if (!String.IsNullOrEmpty(outputAssembly)) tempPath = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(outputAssembly)); if (!String.IsNullOrEmpty(outputAssembly) && !outputAssembly.EqualIgnoreCase(".dll")) { tempPath = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(outputAssembly)); } //if (!String.IsNullOrEmpty(tempPath) && !Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath); //var srcpath = tempPath.CombinePath("src").EnsureDirectory(false); var files = new List <String>(); foreach (var item in tmp.Templates) { // 输出模版内容,为了调试使用 File.WriteAllText(tempPath.CombinePath(item.Name).EnsureDirectory(true), item.Content); if (item.Included) { continue; } var name = item.Name.EndsWithIgnoreCase(".cs") ? item.Name : item.ClassName; // 猜测后缀 var p = name.LastIndexOf("_"); if (p > 0 && name.Length - p <= 5) { name = name.Substring(0, p) + "." + name.Substring(p + 1, name.Length - p - 1); } else if (!name.EndsWithIgnoreCase(".cs")) { name += ".cs"; } //name = Path.Combine(tempPath, name); //name = srcpath.CombinePath(name); // 必须放在同一个目录,编译时会搜索源码所在目录 name = tempPath.CombinePath(Path.GetFileNameWithoutExtension(name) + "_src" + Path.GetExtension(name)); File.WriteAllText(name, item.Source); //sb.AppendLine(item.Source); files.Add(name); } #endregion if (!String.IsNullOrEmpty(outputAssembly) && !outputAssembly.EqualIgnoreCase(".dll")) { options.TempFiles = new TempFileCollection(tempPath, false); options.OutputAssembly = Path.Combine(tempPath, outputAssembly); //options.GenerateInMemory = true; options.IncludeDebugInformation = true; } results = provider.CompileAssemblyFromFile(options, files.ToArray()); // 必须从内存字符串编译,否则pdb会定向到最终源代码文件 //results = provider.CompileAssemblyFromSource(options, new String[] { sb.ToString() }); } else { options.GenerateInMemory = true; results = provider.CompileAssemblyFromSource(options, tmp.Templates.Where(e => !e.Included).Select(e => e.Source).ToArray()); } #region 编译错误处理 if (results.Errors.Count > 0) { Errors.AddRange(results.Errors); var sb = new StringBuilder(); CompilerError err = null; foreach (CompilerError error in results.Errors) { error.ErrorText = error.ErrorText; //if (String.IsNullOrEmpty(error.FileName)) error.FileName = inputFile; if (!error.IsWarning) { var msg = error.ToString(); if (sb.Length < 1) { String code = null; // 屏蔽因为计算错误行而导致的二次错误 try { code = tmp.FindBlockCode(error.FileName, error.Line); } catch { } if (code != null) { msg += Environment.NewLine; msg += code; } err = error; } else { sb.AppendLine(); } sb.Append(msg); } } if (sb.Length > 0) { var ex = new TemplateException(sb.ToString()); ex.Error = err; throw ex; } } else { try { options.TempFiles.Delete(); } catch { } } #endregion if (!results.Errors.HasErrors) { try { return(results.CompiledAssembly); } catch { } } return(null); }