/// <summary> /// </summary> /// <param name="cSharpCode"></param> /// <param name="TempFileFolderName">Define this for debugging purposes</param> /// <returns></returns> internal static Assembly CompileCSharpCode(string cSharpCode, params string[] DebuggingTempFileDirectoryNameParts) { bool IncludeDebugInformation = #if DEBUG true; #else false; #endif int key = Math.Abs(cSharpCode.GetHashCode() ^ IncludeDebugInformation.GetHashCode() ^ typeof(Runtime).Assembly.FullName.GetHashCode() ^ WindowsIdentity.GetCurrent().User.Value.GetHashCode() // just incase the user changes due to an apppool change ); if (!CompileCSharpCodeAssemblies.ContainsKey(key)) { CompilerParameters _CompilerParameters = new CompilerParameters { IncludeDebugInformation = IncludeDebugInformation, GenerateExecutable = false, GenerateInMemory = false, WarningLevel = 0 }; // it was unknown at them time of this writting if (!string.IsNullOrWhiteSpace(CompileCSharpCodeDefaultOutDirectory)) { _CompilerParameters.OutputAssembly = CompileCSharpCodeDefaultOutDirectory + "\\" + Base36.Encode(key) + ".dll"; } if (File.Exists(_CompilerParameters.OutputAssembly)) { CompileCSharpCodeAssemblies[key] = Assembly.LoadFile(_CompilerParameters.OutputAssembly); } else { // Combine & normalize (different paths that load to the same dll) lists of referenced assemblies. Consider our custom list (UsingNamespaces.Values) & whatever is currently loaded into the AppDomain.This ensures the newly compiled object will have everything it needs. Dictionary <string, string> ReferenceAssembliesDic = new Dictionary <string, string>(); foreach (string AppDomainAssemFileName in AppDomain.CurrentDomain.GetAssemblies().Where(m => !m.IsDynamic).Select(m => m.Location)) { if (File.Exists(AppDomainAssemFileName)) { foreach ( string DirectoryName in new[] { new FileInfo(AppDomainAssemFileName).DirectoryName, @".", @".\bin", @".\bin\debug", @".\bin\release" }) { if (Directory.Exists(DirectoryName)) { foreach (FileInfo _FileInfo in USING_NAMESPACES .Values .Select(FileName => String.Format(@"{0}\\{1}", DirectoryName, FileName)) .Where(FilePath => File.Exists(FilePath)) .Select(FilePath => new FileInfo(FilePath)) .Where(_FileInfo => !ReferenceAssembliesDic.ContainsKey(_FileInfo.Name.ToLower()))) { ReferenceAssembliesDic[_FileInfo.Name.ToLower()] = _FileInfo.FullName; } } } } } _CompilerParameters.ReferencedAssemblies.AddRange(ReferenceAssembliesDic.Values.ToArray()); CompilerResults _CompilerResults = CSharpCodeProvider.CompileAssemblyFromSource(_CompilerParameters, cSharpCode); if (_CompilerResults.Errors.Count == 0) { CompileCSharpCodeDefaultOutDirectory = Path.GetDirectoryName(_CompilerResults.PathToAssembly); CompileCSharpCodeAssemblies[key] = _CompilerResults.CompiledAssembly; } else { new DirectoryInfo(RequestPaths.GetPhysicalApplicationPath(FOLDER_FOR_COMPILE_TEMPORARY_FILES)).mkdir().Attributes = FileAttributes.Hidden; if (DebuggingTempFileDirectoryNameParts != null && DebuggingTempFileDirectoryNameParts.Length > 0) { int i = 0; DirectoryInfo _DirectoryInfo = null; // often there are processes that just won't let there handles go off previous files generated // now we try delete those directories or create a new one with an auto-incremented number when the previous can't be removed do { _DirectoryInfo = new DirectoryInfo( RequestPaths .GetPhysicalApplicationPath( new[] { FOLDER_FOR_COMPILE_TEMPORARY_FILES, StringTransform.SafeIdentifier(string.Join(" ", DebuggingTempFileDirectoryNameParts.Union(new[] { string.Format("{0}", i++) }))) } .ToArray())); try { _DirectoryInfo.rmdir(); } catch (Exception) { } } while (_DirectoryInfo.Exists); _DirectoryInfo.mkdir(); _CompilerParameters.GenerateInMemory = false; _CompilerParameters.IncludeDebugInformation = true; _CompilerParameters.TempFiles = new TempFileCollection(_DirectoryInfo.FullName, true); _CompilerParameters.TreatWarningsAsErrors = true; CSharpCodeProvider.CompileAssemblyFromSource(_CompilerParameters, cSharpCode); throw new Exception(string.Format("\"{0}\" Contains runtime the intermediate files of a runtime build (compile) that failed.", _DirectoryInfo.FullName)); } } } } return(CompileCSharpCodeAssemblies[key]); }
/// <summary> /// Creates a namespace (each DocType, DocRev & it's children reside in a dedicated namespace) that is suitable for /// parsing then reversing to it's original string representations. The transformations to and from DocTypeName/DocRev /// & C# namespace is a lossless operation. The inverse of this method is TryParseDocTypeAndRev. Segments for the /// DocType's actual name are prefixed with "doc", for the DocRev: "rev". Example: /// docMyName200.rev1.rev0.rev56.HERE.ARE.SOME.ADDITIONAL.NS_PARTS /// </summary> /// <param name="DocTypeName"></param> /// <param name="DocRev"></param> /// <param name="AdditionalRootNames"></param> /// <returns>DotTypeName as the root name & DocRev as the second level name if nothing specified in AdditionalRootNames</returns> public static string CalcCSharpNamespace(string DocTypeName, string DocRev, params string[] AdditionalRootNames) { Validate(DocTypeName, DocRev, AdditionalRootNames); string[] DocTypeNameParts = DocTypeName.Split('.').Select(s => String.Format("{0}{1}", DOCTYPENAME_NS_PREFIX, s.ToUpper())).ToArray(); string[] RevParts = DocRev.Split('.').Select(s => String.Format("{0}{1}", DOCREV_NS_PREFIX, s)).ToArray(); string[] OtherParts = AdditionalRootNames == null ? new string[] { } : AdditionalRootNames.Where(s => !String.IsNullOrWhiteSpace(s)).Select(s => String.Format("{0}{1}", ADDITIONAL_NS_PREFIX, StringTransform.SafeIdentifier(s ?? "_"))).ToArray(); return(String.Join(".", DocTypeNameParts.Concat(RevParts).Concat(OtherParts))); }
/// <summary> /// Creates a namespace (each DocType, DocRev & it's children reside in a dedicated namespace) that is suitable for /// parsing then reversing to it's original string representations. The transformations to and from DocTypeName/DocRev /// & C# namespace is a lossless operation. The inverse of this method is TryParseDocTypeAndRev. Segments for the /// DocType's actual name are prefixed with "doc", for the DocRev: "rev". Example: /// docFORM200.rev1.rev0.rev56.HERE.ARE.SOME.ADDITIONAL.NS_PARTS /// </summary> /// <param name="DocTypeName"></param> /// <param name="DocRev"></param> /// <param name="AdditionalRootNames"></param> /// <returns>DotTypeName as the root name & DocRev as the second level name if nothing specified in AdditionalRootNames</returns> internal static string CalcCSharpFullname(string DocTypeName, string DocRev, params string[] AdditionalRootNames) { // validate arguments if (INVALID_CSHARP_NAMESPACE_PART_MATCH.IsMatch(DocTypeName) | String.IsNullOrWhiteSpace(DocTypeName)) { throw new ArgumentException(String.Format("\"{0}\" is not a valid DocTypeName for namespace code generation operations"), DocTypeName); } if (INVALID_CSHARP_NAMESPACE_PART_MATCH.IsMatch(DocRev) | String.IsNullOrWhiteSpace(DocRev)) { throw new ArgumentException(String.Format("\"{0}\" is not a valid DocRev for namespace code generation operations"), DocRev); } if (AdditionalRootNames != null) { foreach (string test in AdditionalRootNames) { if (!String.IsNullOrWhiteSpace(test)) { if (INVALID_CSHARP_NAMESPACE_PART_MATCH.IsMatch(test)) { throw new ArgumentException(String.Format("\"{0}\" is not valid for namespace code generation operations"), test); } } } } string[] DocTypeNameParts = DocTypeName.Split('.').Select(s => String.Format("{0}{1}", DOCTYPENAME_NS_PREFIX, s.ToUpper())).ToArray(); string[] RevParts = DocRev.Split('.').Select(s => String.Format("{0}{1}", DOCREV_NS_PREFIX, s.ToUpper())).ToArray(); string[] OtherParts = AdditionalRootNames == null ? new string[] {} : AdditionalRootNames.Where(s => !String.IsNullOrWhiteSpace(s)).Select(s => String.Format("{0}{1}", ADDITIONAL_NS_PREFIX, StringTransform.SafeIdentifier(s ?? "_").ToUpper())).ToArray(); return(String.Join(".", DocTypeNameParts.Concat(RevParts).Concat(OtherParts))); }