简介
我正在我的应用中构建插件架构。插件实现了给定的接口 IBasePlugin ,或者从基接口继承的其他接口:
interface IBasePlugin
interface IMainFormEvents : IBasePlugin
主机正在加载插件程序集,然后创建实现 IBasePlugin 接口的任何类的相应对象。
这是加载插件并实例化对象的类:
public class PluginCore
{
#region implement singletone instance of class
private static PluginCore instance;
public static PluginCore PluginCoreSingleton
{
get
{
if (instance == null)
{
instance = new PluginCore();
}
return instance;
}
}
#endregion
private List<Assembly> _PlugInAssemblies = null;
/// <summary>
/// Gets the plug in assemblies.
/// </summary>
/// <value>The plug in assemblies.</value>
public List<Assembly> PlugInAssemblies
{
get
{
if (_PlugInAssemblies != null) return _PlugInAssemblies;
// Load Plug-In Assemblies
DirectoryInfo dInfo = new DirectoryInfo(
Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
"Plugins"
)
);
FileInfo[] files = dInfo.GetFiles("*.dll");
_PlugInAssemblies = new List<Assembly>();
if (null != files)
{
foreach (FileInfo file in files)
{
_PlugInAssemblies.Add(Assembly.LoadFile(file.FullName));
}
}
return _PlugInAssemblies;
}
}
List<IBasePlugin> _pluginsList = null;
/// <summary>
/// Gets the plug ins instances.
/// all the plugins are being instanciated ONCE when this if called for the first time
/// every other call will return the existing classes.
/// </summary>
/// <value>The plug ins instances.</value>
public List<IBasePlugin> PlugInInstances
{
get
{
if (_pluginsList != null) return _pluginsList;
List<Type> availableTypes = new List<Type>();
foreach (Assembly currentAssembly in this.PlugInAssemblies)
availableTypes.AddRange(currentAssembly.GetTypes());
// get a list of objects that implement the IBasePlugin
List<Type> pluginsList = availableTypes.FindAll(delegate(Type t)
{
List<Type> interfaceTypes = new List<Type>(t.GetInterfaces());
return interfaceTypes.Contains(typeof(IBasePlugin));
});
// convert the list of Objects to an instantiated list of IBasePlugin
_pluginsList = pluginsList.ConvertAll<IBasePlugin>(delegate(Type t) { return Activator.CreateInstance(t) as IBasePlugin; });
return _pluginsList;
}
}
问题
目前,任何支持插件的模块都使用 PlugInInstances 属性来检索 IBasePlugins 列表。然后它迭代查询谁正在实现给定子接口的对象。
foreach (IBasePlugin plugin in PluginCore.PluginCoreSingleton.PlugInInstances)
{
if (plugin is IMainFormEvents)
{
// Do something
}
}
我想通过一个接收给定子接口的函数来改进这种技术,并返回这些接口的列表。问题是不应该在调用者中进行任何转换。
伪代码:
void GetListByInterface(Type InterfaceType, out List<InterfaceType> Plugins)
您是否有关于如何实施此建议的建议?
答案 0 :(得分:2)
您可以尝试这样的事情:
void GetListByInterface<TInterface>(out IList<TInterface> plugins) where TInterface : IBasePlugin
{
plugins = (from p in _allPlugins where p is TInterface select (TInterface)p).ToList();
}
答案 1 :(得分:2)
我在锦标赛系统中采用了类似的方法。
您可以在这里查看来源: http://tournaments.codeplex.com/SourceControl/ListDownloadableCommits.aspx
在trunk / TournamentApi / Plugins / PluginLoader.cs中,我已经定义了加载任意程序集插件所需的方法。
我使用的想法是Plugin-Factory-Enumerator类,可以找到,实例化并调用它来生成插件工厂实例。
以下是代码的内容:
List<IPluginFactory> factories = new List<IPluginFactory>();
try
{
foreach (Type type in assembly.GetTypes())
{
IPluginEnumerator instance = null;
if (type.GetInterface("IPluginEnumerator") != null)
{
instance = (IPluginEnumerator)Activator.CreateInstance(type);
}
if (instance != null)
{
factories.AddRange(instance.EnumerateFactories());
}
}
}
catch (SecurityException ex)
{
throw new LoadPluginsFailureException("Loading of plugins failed. Check the inner exception for more details.", ex);
}
catch (ReflectionTypeLoadException ex)
{
throw new LoadPluginsFailureException("Loading of plugins failed. Check the inner exception for more details.", ex);
}
return factories.AsReadOnly();
答案 2 :(得分:0)
我会使用IOC容器来执行插件查找。 MEF可能有点多,但StructureMap是一个单独的DLL,内置支持这个开箱即用。
您可以扫描包含实现接口的对象的程序集的文件夹,并轻松将其加载到应用程序中。 StructureMap on SourceForge
在ObjectFactory的Configure方法中扫描的示例:
Scan(scanner =>
{
string assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
scanner.AssembliesFromPath(assemblyPath, assembly => { return assembly.GetName().Name.StartsWith("Plugin."); });
scanner.With(typeScanner);
});
类型扫描程序实现ITypeScanner,并且可以检查类型是否检查类型是否可分配给相关的接口类型。附带的文档链接中有很好的例子。