插件系统:如何处理主机应用程序和插件之间的事件(Plugin-system: How to hand

2019-10-30 02:53发布

注:我需要使用.NET 3.5

我的测试应用程序三个部分(不同项目和不同的dll文件); 主机的应用程序,插件,SDK和测试插件。

主机应用程序是一个WPF应用程序与一个区域在从插件视图加载。 插件是通过反射加载。 这部分工作像预想的那样。

该SDK包含了一个插件可以实现常见接口。 我的一个接口有该插件必须实现一个事件,当它的触发,主要应用需要倾听它,执行基于该自定义EventArgs的一个动作。 该SDK从两个主机应用和插件引用。

首先我的通用插件加载器:

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;
    }
}

与我想我的插件事件自定义事件参数太多接口直到实施和

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

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

从我的插件事件处理程序

public event EventHandler<JournalLineEventArgs> LineAdding;

在我的主机应用程序,我加载插件列表,然后添加事件处理

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

这里的主要问题是,当我从我的插件引发事件它给了我一个空引用异常。 我认为 ,这可能是因为主机应用程序知道有关该插件的事件,但该插件不知道什么是听它-是吗? ;)不过,我怎样才能使这项工作?

---- UPDATE 2015年5月26日15:08 ----

我暂且称它通过绑定到一个WPF按钮的命令:

public ICommand JournalLineCommand
{
    get
    {
        var eventArgs = new JournalLineEventArgs()
        {
            LineNumber = TextField
        };             
        return new RelayCommand(() => LineAdding(this, eventArgs));
    }
}

当我尝试提高它的情况下是空的。

Answer 1:

我劝你重新考虑你的应用程序使用标准的解决方案,以你的问题的架构。

至于阿隆指出,你可以使用一个EventAggregator的发布和订阅您的整个应用程序中的事件。 你可以使用任何的许多实现是在那里的,这里是一个使用轻量级的一个简单的例子Caliburn.Micro.EventAggregator :

样本事件:

public class SampleEvent
{
    public SampleEvent(int lineNumber)
    {
        LineNumber = lineNumber;
    }

    public int LineNumber { get; private set; }
}

示例发布:

public class Publisher
{
    public Publisher(IEventAggregator eventAggregator)
    {
        EventAggregator = eventAggregator;            
    }

    public void PublishLineNumber(int lineNumber)
    {
        EventAggregator.Publish(new SampleEvent(lineNumber));
    }

    public IEventAggregator EventAggregator { get; private set; }
}

示例用户:

public class Subscriber : IHandle<SampleEvent>
{
    public Subscriber(IEventAggregator eventAggregator)
    {
        EventAggregator = eventAggregator;
        EventAggregator.Subscribe(this);
    }
    public IEventAggregator EventAggregator { get; private set; }

    public void Handle(SampleEvent message)
    {
        Console.WriteLine(message.LineNumber);
    }
}

主要方法:

static void Main(string[] args)
    {
        EventAggregator eventAggregator = new EventAggregator();

        Publisher publisher = new Publisher(eventAggregator);
        Subscriber subscriber = new Subscriber(eventAggregator);

        publisher.PublishLineNumber(5);

        Console.ReadLine();
    }

至于加载插件,我会建议你使用MEF导出/导入。

您可以使用.NET 3.5使用这两者



Answer 2:

你不应该推倒重来。 Microsoft模式的团队已经得到了库与一个插件架构编写WPF应用程序。

Install-Package Prism.PubSubEvents

https://msdn.microsoft.com/en-us/library/ff921122.aspx

编辑:对于那些谁仍在使用.NET 2.0,当然还有棱镜2.X的

https://msdn.microsoft.com/en-us/library/ff648611.aspx



文章来源: Plugin-system: How to handle events between host application and plugin