【发布时间】:2015-05-26 21:51:18
【问题描述】:
注意:我需要使用 .NET 3.5
我的测试应用分为三个部分(不同的项目和不同的 dll); host-application、plugin-sdk 和 test-plugin。
宿主应用程序是一个 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;
}
这里的主要问题是,当我从插件引发事件时,它会给我一个空引用异常。我认为这可能是因为主机应用程序知道插件事件,但插件不知道有任何东西在听它 - 我说的对吗? ;) 但是我怎样才能使它工作呢?
---- 2015-05-26 15:08 更新----
我暂时通过绑定到 WPF 按钮的命令来调用它:
public ICommand JournalLineCommand
{
get
{
var eventArgs = new JournalLineEventArgs()
{
LineNumber = TextField
};
return new RelayCommand(() => LineAdding(this, eventArgs));
}
}
当我尝试引发它时,事件为空。
【问题讨论】:
-
你能展示你是如何从插件中引发事件的吗?您正在将插件类型加载到 WPF 应用程序,因此您可以将其视为 WPF 应用程序的一部分。一般来说,如果你得到 NullReferenceException 你有错误的提升代码,请参阅stackoverflow.com/questions/2123608/…。
-
你在提升它之前检查它是否不为空?
-
如果
LineAdding事件可以在您创建实例 (Activator.CreateInstance) 和初始化它(即在InitializeIJournalPlugins中附加处理程序)之间的某处触发,那么它显然会为空。确保在 让此插件实例执行其他任何操作之前附加处理程序。
标签: c# .net events plugins reflection