using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Windows.Forms; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.TIProGUI; namespace TradeIdeas.Extensions { /// /// This is the called on each extension which supports it. This is called after loading the /// config files, but before loading the default layout. /// public interface IMainInit { void MainInit(); } /// /// This is the preferred way to talk with the main program. /// public interface IMainProgram { /// /// This is the preferred way to expose a window to the user. This creates a new menu /// item on the tools menu. This is only aimed at extensions. Presumably when this /// becomes real, it will be added to the menu in a more appropriate place. /// /// The user visible name. (Currently there is no attempt at using translations.) /// The Click event for the menu item. /// This is a pointer to the newly created menu item. This allows for further customization, if required. System.Windows.Forms.ToolStripMenuItem AddToToolsMenu(string name, Action callback); /// /// This is to add to the REAL Tools menu. AddToToolsMenu() is actually being used to add /// to the New menu on the main form. /// /// The user visible name. (Currently there is no attempt at using translations.) /// The Click event for the menu item. /// This is a pointer to the newly created menu item. This allows for further customization, if required. System.Windows.Forms.ToolStripMenuItem AddToRealToolsMenu(string name, Action callback); /// /// This will allow us to add a panel to the toolbar. /// /// /// /// System.Windows.Forms.ToolStripControlHost AddPanelToToolBar(Action liveCallback, Action simCallback); /// /// How to access the server. /// /// Typically the main program hands this to each new window. Currently there is exactly one of these, /// but a main program certainly could create more and give different ones to different windows. /// Typically a window will take this as an argument to the constructor. /// IConnectionMaster ConnectionMaster { get; } string AppNameInternal { get; } // new properties to get dock panel settings and layout manager from main program - RVH20210506 bool DockPanelMode { get; } string MainDockPanelName { get; } string MainDockPanelTitle { get; } /// /// LayoutManager defined in the main program. /// LayoutManager LayoutManager { get; } /// /// This will allow us to add a monitor control to right of the tick panel. /// /// The control to add. /// void AddMonitorControl(Control control); } /// /// This is primarily aimed at the main program. This finds all extensions. /// /// If you want to provide an extension, create a DLL named *Extension.DLL and put it in the same /// directory as the main program. Within that, create one or more class with a mathod with the /// following name and signature: /// public static IList< Object > GetExtensions(Object mainProgram) /// /// Note that the input and outputs are all of type Object. For maximum flexibility these are /// cast to different interfaces as needed. Some extensions and some main programs may not /// implement all interfaces. /// public class ExtensionHelper { private string _fileFilter = "*Extension.DLL"; public string FileFilter { get { return _fileFilter; } set { _fileFilter = value; } } private string _extensionMethodName = "GetExtensions"; public string ExtensionMethodName { get { return _extensionMethodName; } set { _extensionMethodName = value; } } private List _extensions = new List(); public IList Extensions { get { return _extensions; } } public IList GetExtensions() where T : class { IList result = new List(); foreach (object possible in _extensions) { T found = possible as T; if (null != found) result.Add(found); } return result; } /// /// This helps when you are in the debugger. Otherwise is it not used. /// private Exception _unexpectedFailure; private void LoadFromDirectory(String directoryName) { try { string[] filenames = Directory.GetFiles(directoryName, _fileFilter); foreach (string extensionFileName in filenames) { LoadFromFile(extensionFileName); } } catch (Exception ex) { _unexpectedFailure = ex; } } private HashSet _extensionFileNamesLoaded = new HashSet(); /// /// Try to load all extensions from a specific file. This is all wrapped in a big try block. /// Most errors will be ignored and will all look the same. It is safe, for example, always /// to try to load a file, rather than looking to see if the file exists, first. /// /// /// The file to load. This must be an absolute path name. See Path.GetFullPath. /// private void LoadFromFile(String extensionFileName) { try { string fileName = Path.GetFileName(extensionFileName); if (_extensionFileNamesLoaded.Contains(fileName)) return; Assembly assembly = Assembly.LoadFile(extensionFileName); foreach (Type type in assembly.GetTypes()) { MethodInfo methodInfo = type.GetMethod(_extensionMethodName); if (null != methodInfo) { try { Object result = methodInfo.Invoke(null, _args); _extensions.AddRange(result as IList); _extensionFileNamesLoaded.Add(fileName); } catch (Exception ex) { _unexpectedFailure = ex; } } } } catch (Exception ex) { _unexpectedFailure = ex; } } private readonly Object[] _args; private bool _devMode = false; /// /// Find all extensions. /// /// This will be sent to each extension in the initialization process. public ExtensionHelper(IMainProgram mainProgram, bool devMode = false) { _devMode = devMode; _args = new Object[1]; HelperStartup(mainProgram); } /// /// Find all extensions. /// /// This will be sent to each extension in the initialization process. /// This is the file filter to use for extension DLLs. Default is *Extension.DLL /// This is the method name to look for in each DLL. Default is GetExtensions public ExtensionHelper(IMainProgram mainProgram, string fileFilter, string extensionMethodName) { _args = new Object[1]; _fileFilter = fileFilter; _extensionMethodName = extensionMethodName; HelperStartup(mainProgram); } private void HelperStartup(IMainProgram mainProgram) { _args[0] = mainProgram; LoadFromDirectory(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)); if (_devMode) { //LoadFromFile(Path.GetFullPath(@"..\..\..\TIProDevExtension\bin\Release\TIProDevExtension.dll")); //LoadFromFile(Path.GetFullPath(@"..\..\..\TIProDevExtension\bin\Debug\TIProDevExtension.dll")); string extensionsDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\devextensions"; LoadFromDirectory(extensionsDirectory); } } } }