/// <summary> /// Dispose the object /// </summary> public void Dispose() { // Dispose notifiers foreach (var cnf in s_configuration.Targets) { if (cnf.Notifier is IDisposable) { (cnf.Notifier as IDisposable).Dispose(); } } // Flush the queue Hl7MessageQueue.Current.Flush(); if (m_threadPool != null) { m_threadPool.Dispose(); } }
static void Main(string[] args) { Console.WriteLine("XML ITS1 Formatter Pregenerator Utility"); Console.WriteLine("Copyright (C) 2012, Mohawk College of Applied Arts and Technology"); ParameterParser <Parameters> parser = new ParameterParser <Parameters>(); try { var arguments = parser.Parse(args); if (arguments.ShowHelp) { ShowHelp(); return; } // Generate formatter utility MARC.Everest.Formatters.XML.ITS1.CodeGen.TypeFormatterCreator creator = new MARC.Everest.Formatters.XML.ITS1.CodeGen.TypeFormatterCreator(); // Create code namespace CodeNamespace ns = new CodeNamespace(arguments.TargetNs); // Load assembly Assembly rmimAssembly = Assembly.LoadFile(arguments.AssemblyFile); List <Type> rmimTypes = new List <Type>(); if (arguments.Interactions != null) { foreach (var s in arguments.Interactions) { rmimTypes.Add(rmimAssembly.GetTypes().First(o => o.Name == s)); } } else { rmimTypes.AddRange(rmimAssembly.GetTypes()); } // Validate parameters if (rmimTypes.Count == 0) { throw new ArgumentException("Type array must have at least one element", "t"); } // Create a list of types (a todo list) that represent the types we want to format List <Type> types = new List <Type>(200); // Iterate through types and create formatter // Iterate throgh the types foreach (Type type in rmimTypes) { if (type.Assembly != rmimAssembly) { throw new InvalidOperationException("All types must belong to the same revision assembly"); } GetUniqueTypes(type, types, true); } // Waith thread pool WaitThreadPool wtp = new WaitThreadPool(); try { // Create type definitions foreach (Type t in types) { // Check if we need to gen this type if (t.GetCustomAttributes(typeof(StructureAttribute), false).Length == 0 || s_formatterGenerated.Contains(t)) { continue; } s_formatterGenerated.Add(t); // Structure Attribute StructureAttribute sta = t.GetCustomAttributes(typeof(StructureAttribute), false)[0] as StructureAttribute; // Type formatter creator TypeFormatterCreator crtr = new TypeFormatterCreator(); // Reset event crtr.CodeTypeDeclarationCompleted += new CreateTypeFormatterCompletedDelegate(delegate(CodeTypeDeclaration result) { // Add to the code currently created if (result != null) { lock (ns) ns.Types.Add(result); } }); // Helper result wtp.QueueUserWorkItem(crtr.CreateTypeFormatter, t); } // Wait for final pool to clear wtp.WaitOne(); } finally { wtp.Dispose(); } if (ns.Types.Count == 0) { Console.WriteLine("Didn't create any formatter helpers..."); return; } // Setup compiler and referenced assemblies CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider(); using (TextWriter tw = File.CreateText(arguments.Output ?? "output.cs")) csharpCodeProvider.GenerateCodeFromNamespace(ns, tw, new System.CodeDom.Compiler.CodeGeneratorOptions() { IndentString = "\t" }); } catch (ArgumentNullException) { ShowHelp(); } catch (Exception e) { Console.WriteLine(e.ToString()); return; } finally { } #if DEBUG Console.ReadKey(); #endif }
/// <summary> /// Creates the formatter assembly for the specified types /// </summary> public Assembly CreateFormatterAssembly(Type[] rmimTypes, List <IStructureFormatter> aides, bool generateDeep) { // Enter and lock lock (m_syncObject) { while (m_codeGenBlocking) { Monitor.Wait(m_syncObject); } m_codeGenBlocking = true; } // Create code namespace CodeNamespace ns = new CodeNamespace(String.Format("MARC.Everest.Formatters.XML.ITS1.d{0}", Guid.NewGuid().ToString("N"))); List <Assembly> rmimAssemblies = new List <Assembly>() { rmimTypes[0].Assembly }; try { // Validate parameters if (rmimTypes.Length == 0) { throw new ArgumentException("Type array must have at least one element", "t"); } // Scan all classes in any graph aides List <string> graphAidesClasses = new List <string>(200); foreach (IStructureFormatter isf in aides) { graphAidesClasses.AddRange(isf.HandleStructure); } // Create a list of types (a todo list) that represent the types we want to format List <Type> types = new List <Type>(200); // Iterate through types and create formatter if (generateDeep) { foreach (var type in Array.FindAll <Type>(rmimAssemblies[0].GetTypes(), o => o.IsClass && !o.IsAbstract && o.GetCustomAttributes(typeof(StructureAttribute), false).Length > 0)) { //if (!rmimAssemblies.Contains(type.Assembly)) // rmimAssemblies.Add(type.Assembly); GetUniqueTypes(type, types, true); } } else { // Iterate throgh the types foreach (Type type in rmimTypes) { //if (!rmimAssemblies.Contains(type.Assembly)) // throw new InvalidOperationException("All types must belong to the same revision assembly"); GetUniqueTypes(type, types, false); } } // Waith thread pool WaitThreadPool wtp = new WaitThreadPool(); try { // Create type definitions foreach (Type t in types) { // Check if we need to gen this type if (t.GetCustomAttributes(typeof(StructureAttribute), false).Length == 0 || s_formatterGenerated.Contains(t)) { continue; } s_formatterGenerated.Add(t); // Scan and add base type Type dScan = t.BaseType; while (dScan != null && dScan != typeof(System.Object)) { if (!rmimAssemblies.Contains(dScan.Assembly)) { rmimAssemblies.Add(dScan.Assembly); } dScan = dScan.BaseType; } // Structure Attribute StructureAttribute sta = t.GetCustomAttributes(typeof(StructureAttribute), false)[0] as StructureAttribute; // Is this type already handled by a helper formatter? bool hasHelper = graphAidesClasses.Contains(sta.Name); // Compile if helper is not available if (!hasHelper) { // Type formatter creator TypeFormatterCreator crtr = new TypeFormatterCreator(); // Reset event crtr.CodeTypeDeclarationCompleted += new CreateTypeFormatterCompletedDelegate(delegate(CodeTypeDeclaration result) { // Add to the code currently created if (result != null) { lock (ns) { ns.Types.Add(result); } } }); // Helper result wtp.QueueUserWorkItem(crtr.CreateTypeFormatter, t); } } // Wait for final pool to clear wtp.WaitOne(); } finally { wtp.Dispose(); } if (ns.Types.Count == 0) { return(null); } } finally { m_codeGenBlocking = false; lock (m_syncObject) Monitor.Pulse(m_syncObject); } // Setup compiler and referenced assemblies CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider(); CodeCompileUnit compileUnit = new CodeCompileUnit(); compileUnit.Namespaces.Add(ns); compileUnit.ReferencedAssemblies.Add(typeof(II).Assembly.Location); compileUnit.ReferencedAssemblies.Add(typeof(ITypeFormatter).Assembly.Location); // Was this assembly loaded directly from disk or from a byte array foreach (var asm in rmimAssemblies) { compileUnit.ReferencedAssemblies.Add(asm.Location); } compileUnit.ReferencedAssemblies.Add("System.dll"); compileUnit.ReferencedAssemblies.Add("System.Xml.dll"); // Assembly info CodeAttributeDeclaration cadecl = new CodeAttributeDeclaration("System.Reflection.AssemblyVersion", new CodeAttributeArgument[] { new CodeAttributeArgument(new CodePrimitiveExpression("1.0.*")) }); compileUnit.AssemblyCustomAttributes.Add(cadecl); // Setup compiler CompilerParameters compilerParms = new CompilerParameters(); compilerParms.GenerateInMemory = !generateDeep; compilerParms.WarningLevel = 1; compilerParms.TempFiles.KeepFiles = generateDeep; // Compile code dom // To see the generated code, set a breakpoint on the next line. // Then take a look at the results.TempFiles array to find the // path to the generated C# files CompilerResults results = csharpCodeProvider.CompileAssemblyFromDom(compilerParms, new CodeCompileUnit[] { compileUnit }); if (results.Errors.HasErrors) { throw new Exceptions.FormatterCompileException(results); } else { Assembly a = !generateDeep ? results.CompiledAssembly : Assembly.LoadFile(results.PathToAssembly); AddFormatterAssembly(a); return(a); } }