mardi 26 mai 2015

Plugin-system: How to handle events between host application and plugin

My test application is in three parts (different projects and different dlls); host-application, plugin-sdk and test-plugin.

The host application is a WPF application with an area to load in views from the plugins. Plugins is loaded through Reflection. This part work as supposed.

The SDK contains common interfaces that a plugin can implement. One of my interfaces has an event that the plugin must implement and when it's triggered, the main application need to listen for it, to perform an action based on the a custom EventArgs. The SDK is referenced from both the host-application and the plugin.

First my generic plugin-loader:

public static class GenericPluginLoader<T>
{
    public static ICollection<T> LoadPlugins(string path)
    {
        string[] dllFileNames = null;

        if (Directory.Exists(path))
        {
            dllFileNames = Directory.GetFiles(path, "*.dll");

            var assemblies = new List<Assembly>(dllFileNames.Length);
            foreach (var dllFile in dllFileNames)
            {
                var an = AssemblyName.GetAssemblyName(dllFile);
                var assembly = Assembly.Load(an);
                assemblies.Add(assembly);
            }

            var pluginType = typeof(T);
            var pluginTypes = new List<Type>();
            foreach (var assembly in assemblies)
            {
                if (assembly != null)
                {
                    Type[] types = assembly.GetTypes();

                    foreach (var type in types)
                    {
                        if (type.IsInterface || type.IsAbstract)
                        {
                            continue;
                        }
                        else
                        {
                            if (type.GetInterface(pluginType.FullName) != null)
                            {
                                pluginTypes.Add(type);
                            }
                        }
                    }
                }
            }

            var plugins = new List<T>(pluginTypes.Count);
            foreach (var type in pluginTypes)
            {
                var plugin = (T)Activator.CreateInstance(type);
                plugins.Add(plugin);
            }

            return plugins;
        }

        return null;
    }
}

The interface with an event I want my plugin til implement and the custom event args too

public class JournalLineEventArgs : EventArgs
{
    public string LineNumber { get; set; }
}

public interface IJournalPlugin
{
    event EventHandler<JournalLineEventArgs> LineAdding;
}

The event handler from my plugin

public event EventHandler<JournalLineEventArgs> LineAdding;

In my host application I load the plugins to a list and then add the event handler

private void InitializeIJournalPlugins()
{
    foreach (var plugin in journalPlugins) 
        plugin.LineAdding += OnJournalAdd;
}

The main problem here is that when I raise the event from my plugin it gives me a null-reference exception. I think that this may be because the host application knows about the plugin event but the plugin does not know that anything is listening to it - am I right? ;) But how can I make this work?





Aucun commentaire:

Enregistrer un commentaire