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

C# 检索实现给定接口的对象列表,c#,generics,architecture,plugins,interface,C#,Generics,Architecture,Plugins,Interface,介绍 我正在我的应用程序中构建插件架构。插件实现给定的接口IBasePlugin,或从基本接口继承的其他接口: interface IBasePlugin interface IMainFormEvents : IBasePlugin 主机正在加载插件程序集,然后为实现IBasePlugin接口的任何类创建适当的对象 这是加载插件并实例化对象的类: public class PluginCore { #region implement singletone instance of

介绍

我正在我的应用程序中构建插件架构。插件实现给定的接口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;
         }
     }
我想通过使用一个函数来改进这项技术,该函数接收给定的子接口,并返回这些接口的列表。问题是不应该在调用者中进行强制转换

伪代码:

void GetListByInterface(Type InterfaceType, out List<InterfaceType> Plugins)
void GetListByInterface(键入InterfaceType,列出插件)

您对如何实现这一点有什么建议吗?

您可以尝试以下方法:

void GetListByInterface<TInterface>(out IList<TInterface> plugins) where TInterface : IBasePlugin
{
  plugins = (from p in _allPlugins where p is TInterface select (TInterface)p).ToList();
}
void GetListByInterface(out-IList插件),其中TInterface:IBasePlugin
{
plugins=(来自p,其中p是TInterface select(TInterface)p.ToList();
}

您可以尝试以下方法:

void GetListByInterface<TInterface>(out IList<TInterface> plugins) where TInterface : IBasePlugin
{
  plugins = (from p in _allPlugins where p is TInterface select (TInterface)p).ToList();
}
void GetListByInterface(out-IList插件),其中TInterface:IBasePlugin
{
plugins=(来自p,其中p是TInterface select(TInterface)p.ToList();
}

我在锦标赛系统中使用了类似的方法

您可以在此处查看源代码:

在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();
List factories=new List();
尝试
{
foreach(在assembly.GetTypes()中键入Type)
{
IPluginEnumerator实例=null;
if(type.GetInterface(“IPluginEnumerator”)!=null)
{
instance=(IPluginEnumerator)Activator.CreateInstance(类型);
}
if(实例!=null)
{
AddRange(instance.EnumerateFactorys());
}
}
}
catch(SecurityException-ex)
{
抛出新的LoadPluginsFailureException(“加载插件失败。有关更多详细信息,请检查内部异常。”,ex);
}
捕获(ReflectionTypeLoadException ex)
{
抛出新的LoadPluginsFailureException(“加载插件失败。有关更多详细信息,请检查内部异常。”,ex);
}
返回工厂。AsReadOnly();

我在锦标赛系统中使用了类似的方法

您可以在此处查看源代码:

在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();
List factories=new List();
尝试
{
foreach(在assembly.GetTypes()中键入Type)
{
IPluginEnumerator实例=null;
if(type.GetInterface(“IPluginEnumerator”)!=null)
{
instance=(IPluginEnumerator)Activator.CreateInstance(类型);
}
if(实例!=null)
{
AddRange(instance.EnumerateFactorys());
}
}
}
catch(SecurityException-ex)
{
抛出新的LoadPluginsFailureException(“加载插件失败。有关更多详细信息,请检查内部异常。”,ex);
}
捕获(ReflectionTypeLoadException ex)
{
抛出新的LoadPluginsFailureException(“加载插件失败。有关更多详细信息,请检查内部异常。”,ex);
}
返回工厂。AsReadOnly();

我会使用IOC容器来执行插件查找。MEF可能有点多,但StructureMap是一个单独的DLL,并且内置了对这种开箱即用的支持

您可以扫描文件夹中包含实现接口的对象的程序集,并轻松地将它们加载到应用程序中。

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

我想使用IOC容器来执行插件查找。MEF可能有点多,但StructureMap是一个单独的DLL,并且内置了对这种开箱即用的支持

您可以扫描文件夹中包含实现接口的对象的程序集,并轻松地将它们加载到应用程序中。

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

您是否考虑过使用Microsoft的托管扩展性框架@TrueWill:我在家里有这样的代码。几个小时后我会看一看。用类型接口的hashmap创建一个对象查找树。@TrueWill:MEF看起来很有趣,可能会解决比我要求的更多的问题。但就目前而言,我仍然希望找到一个解决方案来解决我的问题。您是否考虑过使用Microsoft的托管可扩展性框架@TrueWill:我在家里有这样的代码。几个小时后我会看一看。用类型接口的hashmap创建一个对象查找树。@TrueWill:MEF看起来很有趣,可能会解决比我要求的更多的问题。但是现在,我仍然想找到一个解决我所问问题的办法。@Andrew:谢谢,正是我想要的。虽然我必须在没有LINQ的情况下实现它,因为我遵守.NET 2。我应该说“所有插件.of type()”,但这并不重要,因为你没有使用LINQ。@Andrew:谢谢,这正是我想要的。虽然我必须在没有LINQ的情况下实现它,因为我有.NET2的遵从性