/// <summary> /// Internal method containing the logic to actually load plugins. /// </summary> /// <remarks>Todo: implement a registry that will keep track of which plugins are enabled or not.</remarks> private void loadPlugins() { LogUtility.Out("[SK] PluginLoader started loading"); DirectoryInfo pluginDir = new DirectoryInfo("plugins"); if (!pluginDir.Exists) { LogUtility.Out("[SK] Created plugin directory."); pluginDir.Create(); } foreach (FileInfo fi in pluginDir.GetFiles("*.dll")) { try { // just load all assemblies, the resolver locate all IPlugin implementations LogUtility.Out("[SK] Loading plugin DLL ('" + fi.Name + "') : "); var assembly = Assembly.LoadFrom(fi.FullName); _loadedAssemblies.Add(assembly); } catch (Exception e) { var survivalKitException = new SurvivalKit.Exceptions.AssemblyLoadException(fi.FullName, "An exception occured while loading a plugin dll ('" + fi.Name + "')", e); LogUtility.Exception(survivalKitException); } } LogUtility.Out("[SK] PluginLoader finished loading"); }
/// <summary> /// Method that will actually resolve the instances. /// </summary> /// <typeparam name="TInstance">The type of the instances we want.</typeparam> /// <returns> /// Returns a list with <see cref="TInstance"/> instances. /// The list could be empty when no implementations were found. /// </returns> public List <TInstance> ResolveInstances <TInstance>(bool onlyLookInPlugins = true) { // get the type once, instead of once every type. IsOfType typeCheckMethod = IsSubclassOf; var typeOfTInstance = typeof(TInstance); if (typeOfTInstance.IsInterface) { typeCheckMethod = ImplementsInterface; } var returnList = new List <TInstance>(); var assemblies = getAssemblyCollection(onlyLookInPlugins); if (assemblies.Count == 0) { LogUtility.Out("[SK] InstanceResolver: No assemblies found."); return(returnList); } foreach (var assembly in assemblies) { LogUtility.Out("[SK] InstanceResolver: Scanning assembly " + assembly.Location); // loop all assemblies, see if it contains types we are looking for. Type[] typesInAssembly = new Type[0]; try { typesInAssembly = assembly.GetTypes(); } catch (Exception exception) { // Not yet able to cover this piece of code with a unit test. var survivalKitException = new SurvivalKit.Exceptions.SurvivalKitPluginException("SK.ResolveInstances", "SurvivalKit.Utility.InstanceResolver", "Unable to extract types from assembly: " + assembly.FullName, exception); LogUtility.Exception(survivalKitException); } foreach (var typeInAssembly in typesInAssembly) { if (typeInAssembly.IsInterface || typeInAssembly.IsAbstract) { continue; } // loop all types in the assembly. only act when it matches our needs. if (typeCheckMethod(typeInAssembly, typeOfTInstance)) { var constructors = typeInAssembly.GetConstructors(); var foundValidConstructor = false; foreach (var item in constructors) { if (item.GetParameters().Length == 0) { foundValidConstructor = true; } } if (!foundValidConstructor) { // there is no constructor without arguments, we can't instantiate those (yet?) continue; } try { var instance = (TInstance)Activator.CreateInstance(typeInAssembly); returnList.Add(instance); } catch (Exception exception) { var wrappedException = new SurvivalKitPluginException("ResolvePlugin", "SurvivalKit.InstanceResolver.ResolveInstances", "Error while invoking constructor", exception); LogUtility.Exception(wrappedException); } } } } return(returnList); }