【问题标题】:List of classes in an assembly C#程序集中的类列表 C#
【发布时间】:2017-04-25 10:02:29
【问题描述】:

我想获取程序集中的类列表,作为输出,我想要一个 List[Interface] 而不是 List[string],因为“Interface”是从中继承我的程序集类的接口。我不知道我的问题是否有意义,但如果有人有答案,我将非常感谢。 我已经尝试过这个解决方案:List of classes in an assembly,但它提供了一个包含类名的列表 [字符串],所以它没有帮助,因为我需要从我的接口继承的类的列表。 谢谢大家,祝大家有个愉快的一天:)

作为我的问题的编辑,我使用了 activator.createinstance(type t) 来创建我的类的实例,所以这里是代码:

   Assembly assembly = typeof(Interface1<double, double>).Assembly;

   List<Interface> Classes = new List<Interface>();

   foreach (Type type in assembly.GetExportedTypes())

   {
      var Attributes = type.GetCustomAttributes<FilterAttribute>();
      //select the classes with attribute [Filter]

      if (Attributes.Any())

      {
                TypeOfFilters.Add(type);

      }

      foreach (var i in TypeOfFilters)

      {
            var inst = Activator.CreateInstance(i);

            Classes.Add((Interface) inst);


      }

   }

我收到错误“System.IO.FileNotFoundException:无法加载文件或程序集”

【问题讨论】:

  • but it didn't work for me! 。好的。怎么样?
  • 这要么是您链接到的问题的欺骗,除非您指定它是如何不起作用的。或者它是题外话,因为您没有在帖子中提供所有相关信息。考虑添加minimal reproducible example,以便清楚您的问题是什么。您可以edit您的问题添加此信息。
  • “没有工作”是什么意思?你有例外吗?出乎意料的结果?你期待什么?请在遇到困难的地方展示您尝试过的方法。
  • 它给了我一个列表,这不是我要找的。​​span>
  • @ABIR 你在找什么?

标签: c# .net class .net-assembly


【解决方案1】:

这是我几周前无聊时开设的一个小课程,这可以满足您的要求 - 如果我正确理解了这个问题。

您的应用程序必须实现 IPlugin,并且必须放在执行目录中的“Plugins”文件夹中。

public interface IPlugin
{
    void Initialize();
}
public class PluginLoader
{
    public List<IPlugin> LoadPlugins()
    {
        List<IPlugin> plugins = new List<IPlugin>();

        IEnumerable<string> files = Directory.EnumerateFiles(Path.Combine(Directory.GetCurrentDirectory(), "Plugins"),
            "*.dll",
            SearchOption.TopDirectoryOnly);

        foreach (var dllFile in files)
        {
            Assembly loaded = Assembly.LoadFile(dllFile);

            IEnumerable<Type> reflectedType =
                loaded.GetExportedTypes().Where(p => p.IsClass && p.GetInterface(nameof(IPlugin)) != null);

            plugins.AddRange(reflectedType.Select(p => (IPlugin) Activator.CreateInstance(p)));
        }

        return plugins;
    }
}

根据 Paul 在 cmets 中的建议,这里有一个使用 MEF 的变体,引用 System.ComponentModel.Composition 命名空间。

namespace ConsoleApplication18
{
    using System;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.IO;
    using System.Linq;

    public interface IPlugin
    {
        void Initialize();
    }
    class Program
    {
        private static CompositionContainer _container;
        static void Main(string[] args)
        {
            AggregateCatalog catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(Directory.GetCurrentDirectory(), "Plugins")));

            _container = new CompositionContainer(catalog);

            IPlugin plugin = null;
            try
            {
                _container.ComposeParts();

                // GetExports<T> returns an IEnumerable<Lazy<T>>, and so Value must be called when you want an instance of the object type.
                plugin = _container.GetExports<IPlugin>().ToArray()[0].Value;
            }
            catch (CompositionException compositionException)
            {
                Console.WriteLine(compositionException.ToString());
            }

            plugin.Initialize();
            Console.ReadKey();
        }
    }
}

和 DLL 文件 - 还引用 System.ComponentModel.Composition 命名空间来设置 ExportAttribute

namespace FirstPlugin
{
    using System.ComponentModel.Composition;

    [Export(typeof(IPlugin))]
    public class NamePlugin : IPlugin
    {
        public void Initialize() { }
    }
}

【讨论】:

  • 如果这是 ABIR 想要的,我会使用 MEF(托管可扩展性框架),而不是通过 Activator 类自己创建实例。 MEF 机制是为了加载和实例化在运行时实现指定接口的类而创建的,是一种更安全的方法。
  • 感谢@PaulWeiland,我只使用过ActivatorDelegate 方法,但也必须看看MEF
  • 我正在将它用于我正在开发的插件框架。先用 Activator.CreateInstance 破解了一些代码,直到我的一个同事将我引导到 MEF。这让我的生活轻松多了。
  • 对于 Op:这里有一个关于 MEF 的简短的简短教程,这里肯定可以看到好处,而不是使用激活器并创建自己的逻辑来从特定目录中获取插件。 codeproject.com/Articles/188054/…
  • 感谢@ColiM 的回答,这正是我所需要的。但我收到错误“System.IO.FileNotFoundException:无法加载文件或程序集”我认为“Directory.GetCurrentDirectory()”的问题给了我一个完全不同的目录“C:\Users\AppData\Local\JetBrains \Installations\ReSharperPlatformVs14" 而不是包含程序集的那个。
【解决方案2】:

如果我正确理解您的问题,应该是这样的:

var list = System.Reflection.Assembly.GetTypes().Where(x => typeof(IYourInterface).IsAssignableFrom(x)).ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多