Пример #1
0
        /// <summary>
        /// Each channel is run in a different thread to prevent interference with other channels.
        /// </summary>
        void _ThreadLoop()
        {
            Action action;

            while (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !_Closing)
            {
                while (_Actions.Count > 0)
                {
                    lock (_Actions)
                    {
                        action = _Actions.Dequeue();
                    }
                    try
                    {
                        action();
                    }
                    catch (Exception ex)
                    {
                        _LastError = ICEController.WriteICEEventError("A queued action '" + action.Method.Name + "' for channel '" + Name + " (" + _GUID + ")' has caused an exception error.", ex);
                    }
                }

                Thread.Sleep(0);
            }
        }
Пример #2
0
        public void _OnStart()
        {
            if (!_CheckInitialized(false))
            {
                _Timer.Dispose();
            }

            if (PluginState == PluginState.Ready || PluginState == PluginState.Paused || PluginState == PluginState.Stopped)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") Starting '" + Name + "' ...");

                    _Plugin.OnStart();
                    PluginState = PluginState.Started;

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' started.");
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error starting ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Returns a list of valid plugin types from the specified assembly.
        /// </summary>
        /// <param name="assembly">The assembly to search.</param>
        /// <param name="suppressErrors">If true, then any exception errors are ignored, and 'null' is returned instead.  Any errors are still recorded in the
        /// event log however.</param>
        public static Type[] GetICEPluginTypes(this Assembly assembly, bool suppressErrors = true)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            try
            {
                List <Type> appList = new List <Type>();

                var types = assembly.GetTypes();

                foreach (var type in types)
                {
                    if (type.IsClass && !type.IsAbstract && typeof(IPlugin).IsAssignableFrom(type))
                    {
                        appList.Add(type);
                    }
                }

                return(appList.ToArray());
            }
            catch (Exception ex)
            {
                var _ex = ICEController.WriteICEEventError("Failed to retrieve plugin types from assembly '" + assembly.FullName + "'.", ex);
                if (!suppressErrors)
                {
                    throw _ex;
                }

                return(new Type[0]); // (error not desired, so return an empty array)
            }
        }
Пример #4
0
        public static bool AddAssembly(string filename, bool throwErrors = false)
        {
            if (!File.Exists(filename))
            {
                var _ex = ICEController.WriteICEEventError("The plugin library (Assembly) file '" + filename + "' does not exist.");
                if (throwErrors)
                {
                    throw _ex;
                }
                return(false);
            }

            Assembly assembly;

            try
            {
                assembly = Assembly.ReflectionOnlyLoadFrom(filename);
            }
            catch (Exception ex)
            {
                var _ex = ICEController.WriteICEEventError("The plugin library (Assembly) file '" + filename + "' is invalid or cannot be loaded for some reason.", ex);
                if (throwErrors)
                {
                    throw _ex;
                }
                return(false);
            }

            return(AddAssembly(assembly, throwErrors));
        }
Пример #5
0
        public bool _OnRun()
        {
            _CheckInitialized();

            var runNext = true;

            if (PluginState == PluginState.Started || PluginState == PluginState.Paused)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") Running '" + Name + "' ...");

                    runNext = _Plugin.OnRun();

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' completed.");
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error running ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
                    runNext = false;
                }
            }

            return(runNext);
        }
Пример #6
0
        /// <summary>
        /// Attempts to load the assembly for this plugin library. Returns true on success, and false otherwise.
        /// </summary>
        /// <param name="throwErrors">If true, then an exception is thrown instead of returning false.</param>
        public bool Load(bool throwErrors = false)
        {
            if (_Assembly == null || _Assembly.ReflectionOnly)
            {
                if (string.IsNullOrEmpty(_Filename))
                {
                    var _ex = ICEController.WriteICEEventError("Cannot load this library: No valid filename was given.");
                    if (throwErrors)
                    {
                        throw _ex;
                    }
                    return(false);
                }

                string libFileToLoad = AppDomain.CurrentDomain.BaseDirectory + _Filename;

                ICEController.WriteICEEventInfo("Loading library '" + libFileToLoad + "'...");

                try
                {
                    _Assembly = Assembly.LoadFile(libFileToLoad);
                }
                catch (Exception ex)
                {
                    var _ex = ICEController.WriteICEEventError("An error occurred trying to load plugin '" + libFileToLoad + "'.", ex);
                    if (throwErrors)
                    {
                        throw _ex;
                    }
                    return(false);
                }
            }

            return(IsLoaded);
        }
Пример #7
0
        // -------------------------------------------------------------------------------------------------------

        public Channels(ICEController controller)
        {
            if (controller == null)
            {
                throw new ArgumentNullException("controller");
            }
            Controller = controller;
        }
Пример #8
0
        // -------------------------------------------------------------------------------------------------------

        public Channel CreateChannel(string name, string guid = null)
        {
            ICEController.WriteICEEventInfo("Creating channel '" + name + "'...");
            Channel channel = new Channel(this, name, guid);

            _Channels.Add(channel);
            return(channel);
        }
Пример #9
0
 /// <summary>
 /// Initializes the plugin.  This is where a plugin's constructor logic should go.
 /// </summary>
 /// <param name="controller">A reference to an ICE controller instance.</param>
 /// <param name="pluginWrapper">A reference to the plugin controller (or the plugin itself for derived types), which contains other methods specific to plugins (such as setting up default name=value properties).</param>
 /// <returns>True if initialization was successful.</returns>
 public virtual void Initialize(ICEController controller, IPluginController pluginWrapper)
 {
     if (_Plugin != null && _Plugin != this)
     {
         _Plugin.Initialize(controller, pluginWrapper);
     }
     throw new NotImplementedException("You must implement an 'IPlugin.Initialize()' method in your own type, or override the existing one for derived types.");
 }
Пример #10
0
        // -------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Creates and returns a plugin instance to run on the channel.
        /// </summary>
        /// <param name="name">The case-sensitive type name, or full type name (i.e. [Namespace].[Type]), of the plugin to create.  Full type names are
        /// searched first before type-only names.</param>
        public Plugin <IPlugin> CreateInstance(string name, string guid)
        {
            ICEController.WriteICEEventInfo("Creating instance for plugin '" + name + "' on channel '" + Name + "'...");

            Plugin <IPlugin> plugin = PluginManager.CreateInstance(this, name, guid);

            if (plugin != null)
            {
                _PluginInstances.Add(plugin);
            }

            return(plugin);
        }
Пример #11
0
 /// <summary>
 /// Initializes the controller singleton instance, and hooks into 'AppDomain.CurrentDomain.UnhandledException' event for error reporting.
 /// The 'Instance' property is not valid until this is called.
 /// </summary>
 public static ICEController Initialize()
 {
     if (_Instance == null)
     {
         WriteICEEventInfo("Initializing ICE controller ...");
         _Instance = new ICEController();
         AppDomain.CurrentDomain.UnhandledException += (_s, _e) =>
         {
             WriteICEEventError("A non-functional exception error has occurred" + (_e.IsTerminating ? " while terminating." : ".")
                                + "  This is usually due to developer or configuration related errors.  Please see inner exception information for more details.", _e.ExceptionObject);
         };
         WriteICEEventInfo("ICE controller initialized.");
     }
     return(_Instance);
 }
Пример #12
0
        // -------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Creates and returns a plugin instance to run on a given channel.
        /// </summary>
        /// <param name="channel">The channel instance to create the plugin in (required).</param>
        /// <param name="name">The case-sensitive type name, or full type name (i.e. [Namespace].[Type]), of the plugin to create.  Full type names are
        /// searched first before type-only names.</param>
        /// <param name="guid">A globally unique ID for this plugin instance (system wide, across all channels). If null or empty, a new GUID will be created automatically.</param>
        public Plugin <IPlugin> CreateInstance(Channel channel, string instanceName, string guid = null)
        {
            if (channel == null)
            {
                throw new ArgumentNullException("A channel reference is required for plugin instances.");
            }

            if (string.IsNullOrEmpty(guid))
            {
                guid = Guid.NewGuid().ToString("N");
            }

            if (channel.GetPluginInstance(instanceName) != null)
            {
                throw new InvalidOperationException("There is already an existing plugin instance with the name '" + instanceName + "'.");
            }

            Plugin <IPlugin> pluginController = null;

            try
            {
                ICEController.WriteICEEventInfo("Creating instance for plugin '" + PluginType.FullName + "' on channel '" + channel.Name + "'...");

                var pluginInstance = PluginType.Assembly.CreateInstance(PluginType.FullName) as IPlugin;

                pluginController = pluginInstance as Plugin <IPlugin>;

                if (pluginInstance != null && pluginController == null)
                {
                    // ... this plugin instance does not derive from the plugin<T> controller class, so we need to wrap it in one ...
                    pluginController         = new Plugin <IPlugin>();
                    pluginController._Plugin = pluginInstance;
                }

                if (pluginController != null)
                {
                    pluginController._Configure(channel, Library, instanceName, pluginController.ActualPlugin, guid);
                }
            }
            catch (Exception ex)
            {
                throw ICEController.WriteICEEventError("Error creating plugin type '" + PluginType.FullName + "'.", ex);
            }

            return(pluginController);
        }
Пример #13
0
        public void _OnClosing()
        {
            _CheckInitialized();

            var typeTitle = TypeTitle;

            try
            {
                ICEController.WriteICEEventInfo("(" + typeTitle + ") Closing '" + Name + "' ...");

                _Plugin.OnClosing();
                PluginState = PluginState.Uninitialized;

                ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' ready for termination.");
            }
            catch (Exception ex)
            {
                SetErrorMessage(ex, "Error closing ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
            }
        }
Пример #14
0
        public void _OnTick()
        {
            _CheckInitialized();

            if (PluginState == PluginState.Started)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") Timer elapsed for '" + Name + "' ...");

                    _Plugin.OnTick();

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' completed.");
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error in timer method for ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
                }
            }
        }
Пример #15
0
        public virtual void Stop()
        {
            _CheckInitialized();

            if (_PluginState == PluginState.Started || _PluginState == PluginState.Paused)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") Stopping '" + _Name + "' ...");

                    _Plugin.OnStop();
                    _PluginState = PluginState.Stopped;

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + _Name + "' stopped.");
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error stopping ", typeTitle.ToLower(), " '", _Name, "' on channel '", _Channel.Name, "'.");
                }
            }
        }
Пример #16
0
        public void _OnPause()
        {
            _CheckInitialized();

            if (PluginState == PluginState.Started)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") Pausing '" + Name + "' ...");

                    _Plugin.OnPause();
                    PluginState = PluginState.Paused;

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' paused.");
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error pausing ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
                }
            }
        }
Пример #17
0
        // -------------------------------------------------------------------------------------------------------

        public void Initialize()
        {
            if (!IsInitialized)
            {
                var typeTitle = TypeTitle;

                try
                {
                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' startup properties:", GetNameValues(), "Initializing ...");

                    LoadData();

                    _Plugin.Initialize(Channel.Controller, this);
                    PluginState = PluginState.Ready;

                    ICEController.WriteICEEventInfo("(" + typeTitle + ") '" + Name + "' initialized.", "Properties after initialization:", GetNameValues());
                }
                catch (Exception ex)
                {
                    SetErrorMessage(ex, "Error initializing ", typeTitle.ToLower(), " '", Name, "' on channel '", Channel.Name, "'.");
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Adds an assembly to the assembly list, returning 'false' if any errors occur, or if the assembly was already added.
        /// <para>Warning: This method recursively traverses the assembly types, and all dependent types, in real-time, and will add any other associated
        /// applications, components, and controls also.</para>
        /// </summary>
        /// <param name="assembly">The assembly to add, which represents a library of plugin types.</param>
        /// <param name="throwErrors">If true, any errors will throw an exception instead of returning false.</param>
        public static bool AddAssembly(Assembly assembly, bool throwErrors = false)
        {
            if (GetLibrary(assembly) == null)
            {
                try
                {
                    if (assembly.GetICEPluginTypes(true).Length == 0)
                    {
                        return(false); // (there are no valid plugins types in this assembly)
                    }
                    var library = AddLibrary(new Library(assembly));

                    var associatedAssemblies = assembly.GetAssociatedAssemblies(); // (get a list of assemblies other than the given 'assembly')

                    if (associatedAssemblies != null)
                    {
                        foreach (var asm in associatedAssemblies)
                        {
                            AddAssembly(asm, throwErrors);
                        }
                    }
                }
                catch (Exception ex)
                {
                    var _ex = ICEController.WriteICEEventError("Failed to read types in plugin assembly '" + assembly.FullName + "' (a DLL may be missing).", ex);
                    if (throwErrors)
                    {
                        throw _ex;
                    }
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Пример #19
0
 /// <summary>
 /// Joins all given parameters into one error message.
 /// </summary>
 /// <param name="exception">An optional exception object, or 'null' if none.</param>
 /// <param name="strings">The strings to use as a single error message.</param>
 public void SetErrorMessage(Exception innerException, params string[] strings)
 {
     _Error = ICEController.WriteICEEventError(strings.Length > 0 ? String.Join("", strings) : "An ICE plugin error has occurred.", innerException);
 }
Пример #20
0
 /// <summary>
 /// Joins all given parameters into one error message.
 /// </summary>
 /// <param name="strings">The strings to use as a single error message.</param>
 public void SetErrorMessage(params string[] strings)
 {
     _Error = ICEController.WriteICEEventError(strings.Length > 0 ? String.Join("", strings) : "An unspecified ICE plugin error has occurred.");
 }