private Type[] GetTypesFromAssembly(string assemblyPath, VisualizationLogWriter logWriter) { try { // Load the assembly Assembly assembly = Assembly.LoadFrom(assemblyPath.Trim()); // Get the list of types in the assembly. (This action will fail if there's missing dependent assemblies) return(assembly.GetTypes()); } catch (ReflectionTypeLoadException ex) { // Error most likely caused by trying to load a type that references a missing dependent assembly. logWriter.WriteError("Could not load assembly {0}: {1}", assemblyPath, ex.Message); // Look into the loader exceptions so we can write out the list of missing dependent assemblies. if (ex.LoaderExceptions != null) { foreach (Exception loaderException in ex.LoaderExceptions) { logWriter.WriteError(loaderException.Message); } } return(new Type[] { }); } catch (Exception ex) { // General error loading assembly logWriter.WriteError("Could not load assembly {0}: {1}", assemblyPath, ex.Message); return(new Type[] { }); } }
private void AddStreamAdapter(Type adapterType, VisualizationLogWriter logWriter, string assemblyPath) { logWriter.WriteLine("Loading StreamAdapter {0} from {1}...", adapterType.Name, assemblyPath); StreamAdapterMetadata streamAdapterMetadata = StreamAdapterMetadata.Create(adapterType, logWriter); if (streamAdapterMetadata != null) { this.streamAdapters.Add(streamAdapterMetadata); } }
private void AddSummarizer(Type summarizerType, VisualizationLogWriter logWriter, string assemblyPath) { logWriter.WriteLine("Loading Summarizer {0} from {1}...", summarizerType.Name, assemblyPath); SummarizerMetadata summarizerMetadata = SummarizerMetadata.Create(summarizerType, logWriter); if (summarizerMetadata != null) { this.summarizers[summarizerType] = summarizerMetadata; } }
private void AddVisualizer(Type visualizationObjectType, VisualizationLogWriter logWriter, string assemblyPath) { // Add both a "Visualize" and a "Visualize in new panel" command metadata logWriter.WriteLine("Loading Visualizer {0} from {1}...", visualizationObjectType.Name, assemblyPath); List <VisualizerMetadata> visualizerMetadata = VisualizerMetadata.Create(visualizationObjectType, this.summarizers, this.streamAdapters, logWriter); if (visualizerMetadata != null) { this.visualizers.AddRange(visualizerMetadata); } }
private static Type GetVisualizationObjectDataType(Type visualizationObjectType, VisualizationLogWriter logWriter) { // Look into the visualization object's base types until we find VisualizationObject<TData> // (whose base type is in turn VisualizationObject). Type type = visualizationObjectType; while ((type != null) && (type.BaseType != typeof(VisualizationObject))) { type = type.BaseType; } // Make sure we ultimately derive from VisualizationObject<TData> if (type == null) { logWriter.WriteError("Could not load visualization object {0} because it does not ultimately derive from VisualizationObject", visualizationObjectType.Name); return(null); } else { // The one and only type argument is the data type of the visualization object return(type.GenericTypeArguments[0]); } }
private static VisualizationPanelTypeAttribute GetVisualizationPanelTypeAttribute(Type visualizationObjectType, VisualizationLogWriter logWriter) { VisualizationPanelTypeAttribute visualizationPanelTypeAttribute = visualizationObjectType.GetCustomAttribute <VisualizationPanelTypeAttribute>(); if (visualizationPanelTypeAttribute == null) { logWriter.WriteError("Visualization object {0} could not be loaded because it is not decorated with a VisualizationPanelTypeAttribute", visualizationObjectType.Name); return(null); } return(visualizationPanelTypeAttribute); }
private static VisualizationObjectAttribute GetVisualizationObjectAttribute(Type visualizationObjectType, VisualizationLogWriter logWriter) { VisualizationObjectAttribute visualizationObjectAttribute = visualizationObjectType.GetCustomAttribute <VisualizationObjectAttribute>(); if (visualizationObjectAttribute == null) { logWriter.WriteError("Visualization object {0} could not be loaded because it is not decorated with a VisualizationObjectAttribute", visualizationObjectType.Name); return(null); } if (string.IsNullOrWhiteSpace(visualizationObjectAttribute.CommandText)) { logWriter.WriteError("Visualization object {0} could not be loaded because its VisualizationObjectAttribute does not specify a Text property", visualizationObjectType.Name); return(null); } if (string.IsNullOrWhiteSpace(visualizationObjectAttribute.IconSourcePath) && string.IsNullOrWhiteSpace(visualizationObjectAttribute.NewPanelIconSourcePath)) { logWriter.WriteError("Visualization object {0} could not be loaded because its VisualizationObjectAttribute does not specify either an IconSourcePath property or a NewPanelIconSourcePath property", visualizationObjectType.Name); return(null); } if (!visualizationObjectAttribute.VisualizationFormatString.Contains(VisualizationObjectAttribute.DefaultVisualizationFormatString)) { logWriter.WriteError("Visualization object {0} could not be loaded because its VisualizationObjectAttribute has an invalid value for the VisualizationFormatString property", visualizationObjectType.Name); return(null); } return(visualizationObjectAttribute); }
/// <summary> /// Creates one or two visualizer metadatas depending on whether a "Visualize in new panel" icon source path was suplied by the visualization object. /// </summary> /// <param name="visualizationObjectType">The visualization object type.</param> /// <param name="summarizers">The list of known summarizers.</param> /// <param name="dataAdapters">The list of known data adapters.</param> /// <param name="logWriter">The log writer where errors should be written to.</param> /// <returns>A list of visualizer metadatas.</returns> public static List <VisualizerMetadata> Create(Type visualizationObjectType, Dictionary <Type, SummarizerMetadata> summarizers, List <StreamAdapterMetadata> dataAdapters, VisualizationLogWriter logWriter) { // Get the visualization object attribute VisualizationObjectAttribute visualizationObjectAttribute = GetVisualizationObjectAttribute(visualizationObjectType, logWriter); if (visualizationObjectAttribute == null) { return(null); } // Get the visualization panel type attribute VisualizationPanelTypeAttribute visualizationPanelTypeAttribute = GetVisualizationPanelTypeAttribute(visualizationObjectType, logWriter); if (visualizationPanelTypeAttribute == null) { return(null); } // Get the message data type for the visualization object. We will get nothing back // if visualizationObjectType does not ultimately derive from VisualizationObject<TData> Type visualizationObjectDataType = GetVisualizationObjectDataType(visualizationObjectType, logWriter); if (visualizationObjectDataType == null) { return(null); } // Get the summarizer type (if the visualizer uses a summarizer) SummarizerMetadata summarizerMetadata = null; if (visualizationObjectAttribute.SummarizerType != null) { if (summarizers.ContainsKey(visualizationObjectAttribute.SummarizerType)) { summarizerMetadata = summarizers[visualizationObjectAttribute.SummarizerType]; } else { logWriter.WriteError("Unable to load visualizer {0} because it relies on summarizer {1} which could not be found.", visualizationObjectType.Name, visualizationObjectAttribute.SummarizerType.Name); return(null); } } // If we have a summarizer, make sure its output type matches the input type of the visualization object if ((summarizerMetadata != null) && (summarizerMetadata.OutputType != visualizationObjectDataType)) { logWriter.WriteError( "Unable to load visualizer {0} with summarizer {1} because the output type of the summarizer ({2}) does not match the input type of the visualizer ({3}) .", visualizationObjectType.Name, summarizerMetadata.SummarizerType.Name, summarizerMetadata.OutputType.Name, visualizationObjectDataType.Name); return(null); } // Work out the input (message) data type: // // 1) If there's a summarizer, use the summarizer's input type // 2) Otherwise, use the visualization object's data type Type dataType = summarizerMetadata != null ? summarizerMetadata.InputType : visualizationObjectDataType; List <VisualizerMetadata> metadatas = new List <VisualizerMetadata>(); // Add the visualization metadata using no adapter Create(metadatas, dataType, visualizationObjectType, visualizationObjectAttribute, visualizationPanelTypeAttribute, null); // Find all the adapters that have an output type that's the same as the visualization object's data type (or summarizer input type) List <StreamAdapterMetadata> usableAdapters = dataAdapters.FindAll(a => dataType == a.OutputType || dataType.IsSubclassOf(a.OutputType)); // Add the visualization metadata using each of the compatible adapters foreach (StreamAdapterMetadata adapterMetadata in usableAdapters) { Create(metadatas, adapterMetadata.InputType, visualizationObjectType, visualizationObjectAttribute, visualizationPanelTypeAttribute, adapterMetadata); } return(metadatas); }
private void DiscoverVisualizerObjects(List <string> assemblies, string visualizerLoadLogFilename) { bool hasErrors = false; // Create the log writer using (FileStream fileStream = File.Create(visualizerLoadLogFilename)) { using (VisualizationLogWriter logWriter = new VisualizationLogWriter(fileStream)) { // Log preamble logWriter.WriteLine("Loading PsiStudio Visualizers ({0})", DateTime.Now.ToString("G")); logWriter.WriteLine("----------------------------------------------------"); logWriter.WriteLine(); foreach (string assembly in assemblies) { logWriter.WriteLine("Search Assembly: {0}...", assembly); } logWriter.WriteLine(); // Note: Visualization object types depend on both summarizer types and stream adapter types, // so we need to make sure those types have all been loaded before we try to load the // visualization object types. Dictionary <Type, string> visualizationObjectTypes = new Dictionary <Type, string>(); foreach (string assemblyPath in assemblies) { // Get the list of types in the assembly Type[] types = this.GetTypesFromAssembly(assemblyPath, logWriter); // Look for attributes denoting visualziation objects, summarizers, and stream adapters. foreach (Type type in types) { if (type.GetCustomAttribute <VisualizationObjectAttribute>() != null) { // Don't load these yet, wait until we've loaded the summarizers and adapters. visualizationObjectTypes[type] = assemblyPath; } if (type.GetCustomAttribute <SummarizerAttribute>() != null) { this.AddSummarizer(type, logWriter, assemblyPath); } if (type.GetCustomAttribute <StreamAdapterAttribute>() != null) { this.AddStreamAdapter(type, logWriter, assemblyPath); } } } // Load all of the visualization object types that were found earlier Dictionary <Type, string> .Enumerator visualizationObjectTypesEnumerator = visualizationObjectTypes.GetEnumerator(); while (visualizationObjectTypesEnumerator.MoveNext()) { this.AddVisualizer(visualizationObjectTypesEnumerator.Current.Key, logWriter, visualizationObjectTypesEnumerator.Current.Value); } // Log complete logWriter.WriteLine(); logWriter.WriteLine("PsiStudio visualizer loading has completed. ({0})", DateTime.Now.ToString("G")); hasErrors = logWriter.HasErrors; } } // If there were any errors while loading the visualizers etc, inform the user and allow him to view the log. if (hasErrors) { MessageBoxWindow dlg = new MessageBoxWindow( Application.Current.MainWindow, "Visualizers Load Errors", "One or more visualizers were not loaded because they contained errors.\r\n\r\nWould you like to see the visualizer load log?", "Yes", "No"); if (dlg.ShowDialog() == true) { // Display the log file in the default application for text files. Process.Start(visualizerLoadLogFilename); } } }