代码之家  ›  专栏  ›  技术社区  ›  Amirshk

检索实现给定接口的对象列表

  •  1
  • Amirshk  · 技术社区  · 15 年前

    简介

    伊巴塞普卢金 ,或从基本接口继承的某些其他接口:

    interface IBasePlugin
    interface IMainFormEvents : 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;
             }
         }
    

    目前,任何支持插件的模块都使用 插件 属性来检索 列表然后,它迭代查询谁正在实现给定子接口的对象。

    foreach (IBasePlugin plugin in PluginCore.PluginCoreSingleton.PlugInInstances)
    {
         if (plugin is IMainFormEvents)
         {
             // Do something
         }
     }
    

    伪代码:

    void GetListByInterface(Type InterfaceType, out List<InterfaceType> Plugins)
    

    您对如何实施这一点有何建议?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Andrew Kennan    15 年前

    您可以尝试以下方法:

    void GetListByInterface<TInterface>(out IList<TInterface> plugins) where TInterface : IBasePlugin
    {
      plugins = (from p in _allPlugins where p is TInterface select (TInterface)p).ToList();
    }
    
        2
  •  2
  •   John Gietzen    15 年前

    您可以在此处查看源代码: http://tournaments.codeplex.com/SourceControl/ListDownloadableCommits.aspx

    在trunk/TournamentApi/Plugins/PluginLoader.cs中,我定义了加载任意程序集插件所需的方法。


    以下是代码的要点:

    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();
    
        3
  •  0
  •   Chris Patterson    15 年前

    我将使用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,并可以检查类型是否可分配给相关接口类型。在所附的文档链接中有一些很好的例子。