C#从文件中添加类而不重新编译

时间:2017-10-08 20:40:44

标签: c#

对于编程类,我需要编写一个插件管理器,它可以处理实现某个接口(IPlugin)的PlugIns(存储它们并为它们分配需要处理的请求)。我已经做到了这一点,到目前为止它已经解决了。

此外,插件管理器需要能够处理/添加第三方插件而无需重新编译整个程序。允许重新启动程序。

我们的教授向我们建议,当重新启动项目时,pluginmanager应该查找在某个文件夹中实现IPlugin的已编译类,并将它们添加到活动插件列表中。

因为我还没有在互联网上发现任何帮助我但我想知道是否有人知道如何做到这一点?

1 个答案:

答案 0 :(得分:0)

您可以使用System.Reflection命名空间。它包含Assembly类,它是在运行时加载.NET程序集所必需的。但请注意,如果加载非.NET程序集,它将抛出BadImageFormatException

加载程序集后,您可以使用Assembly类提供的GetExportedTypes方法获取所有公共类型。你必须过滤它们以检查它们IPlugin是否可以从类型中分配,以及它是否具有商定的构造函数,例如一个空的默认构造函数。

然后,您可以通过调用Invoke对象上的ConstructorInfo或使用Activator类更简单来创建该类型的实例。您必须将创建的对象强制转换为IPlugin。最后一步是使用接口提供的方法和属性来初始化插件。

作为奖励,您可以使用FileSystemWatcher命名空间中的System.IO来监视在指定文件夹中创建的文件。您可以订阅Created事件,然后加载程序集。您必须注意,如果属性FileSystemWatcher设置为false,则EnableRaisingEvents不会调用该事件 - 默认情况下它是。

我将为您提供一个示例,但建议您先尝试实施自己的版本。

    private void LoadAssembly(string path)
    {
        if (!File.Exists(path))
            throw new ArgumentException($"Could not find the file \"{path}\"");

        try
        {
            Assembly asm = Assembly.LoadFile(path);
            foreach (IPlugin plugin in asm.GetExportedTypes()
                .Where(type => typeof(IPlugin).IsAssignableFrom(type) &&
                               type.GetConstructor(Type.EmptyTypes) != null)
                .Select(type => Activator.CreateInstance(type) as IPlugin))
            {
                plugin.Load();
            }
        }
        catch (Exception ex) when (
            ex is FileLoadException ||
            ex is BadImageFormatException)
        {
            // Do something useful
        }
    }