“我该怎么做?”;选择性地;是否在另一个.NET项目中引用类库项目?

“我该怎么做?”;选择性地;是否在另一个.NET项目中引用类库项目?,.net,projects-and-solutions,.net,Projects And Solutions,好的,我有一个使用插件的.NET项目。插件实现为类库(DLL)项目,每个项目构建在各自的文件夹中。主项目不需要插件DLL来运行,但是如果插件DLL可用,它们将用于各种可选功能。插件中的类由Type.GetType()加载 然而,出于我自己的目的,在测试软件时,我希望能够同时开发插件和主应用程序。我已经创建了一个引用所有项目的“主”解决方案文件,因此我可以设置断点并跨程序集边界执行步骤。然而,问题是插件构建到它们自己的目录中,因此我必须以某种方式将插件DLL文件放到Type.GetType()可以

好的,我有一个使用插件的.NET项目。插件实现为类库(DLL)项目,每个项目构建在各自的文件夹中。主项目不需要插件DLL来运行,但是如果插件DLL可用,它们将用于各种可选功能。插件中的类由
Type.GetType()
加载

然而,出于我自己的目的,在测试软件时,我希望能够同时开发插件和主应用程序。我已经创建了一个引用所有项目的“主”解决方案文件,因此我可以设置断点并跨程序集边界执行步骤。然而,问题是插件构建到它们自己的目录中,因此我必须以某种方式将插件DLL文件放到
Type.GetType()
可以找到它们的地方

编辑:为了澄清,我的代码已经在与.exe相同的目录中枚举DLL文件,并查找与给定接口匹配的类(使用
Assembly.LoadFile()
Assembly.GetExportedTypes()
Type.IsAssignableFrom()
)。然后用户选择要启用的插件,我使用
Type.AssemblyQualifiedName
将这些选择保存到数据库中。最后,当我需要使用插件提供的功能时,我使用
Type.GetType()
加载插件类。所有这些都完全符合预期。只是当我构建应用程序时,我得到了一个没有任何插件的.exe副本。我正在寻找一种方法来构造项目和解决方案文件,这样我就可以将主应用程序和插件项目分开,同时仍然能够在VisualStudio中一起调试它们。这有意义吗

到目前为止,我的想法如下:

  • 从主项目添加对插件项目的引用。
    这样做的好处是,它在我的调试环境中始终可以按预期工作,但当我的应用程序在没有插件的情况下部署时,这会导致问题吗?我使用Dependency Walker进行了检查,似乎没有任何由项目引用创建的直接DLL依赖关系。这里有什么隐藏的问题需要了解吗

  • 将所有插件项目更改为构建到同一目标目录中。
    这似乎工作得很好,但它也会弄乱我的构建树,并且会使只开发一个项目而不签出其他项目变得更加困难(现在它们都是Subversion中的兄弟文件夹)

  • 添加生成后脚本以将插件复制到另一个目录。
    这实际上是我目前正在做的,它工作得很好,但它看起来非常粗糙和脆弱。我想换一种方法

  • 查找
    Type.GetType()
    在其他目录中搜索DLL的方法
    这类似于我在Unix系统上使用
    LD\u LIBRARY\u PATH
    。显然,我只想为调试构建启用此功能,因为在发布模式下,这可能会在用户系统上造成许多微妙的问题。但这有可能吗?如果是,怎么做

有趣的是,关于这个问题,它说:

首先要做的是引用我们刚刚创建的类库,并将构建输出设置到同一目录


这对我来说似乎不太理想。有更好的方法吗?

对于插件模型,我会看看
Activator.CreateInstance
Activator.CreateInstanceFrom
方法,甚至看看
Assembly.LoadFrom
。这些方法允许您从“传统”输出目录以外的目录(
bin、debug、release
)中的程序集加载类型

强制
Type.GetType
查找“插件”程序集实际上取决于您如何修改加载程序搜索程序集的策略。例如,您可以设置
AppDomain.PrivateBinPath
属性来更改加载程序将查找引用程序集的子目录

关于第一点“添加对插件项目的引用”。好吧,这将使一个处于一个困难的境地,阻止将来的可扩展性。如果我想制作一个新插件呢?哎哟,现在你没有引用它,所以我想我的插件不会工作了?这就是为什么需要另一种方法。我们将“探测”插件程序集


在一个插件模型中,所有插件都应该针对一个公共接口(或抽象类)工作,而这正是您在加载的任何新插件中寻找的实现。例如:

private void LoadAllPlugins(string path)
{
    foreach(string file in Directory.GetFiles(path, "*.dll"))
    {
        Assembly a = Assembly.LoadFrom(file);
        foreach(Type t in a.GetTypes())
        {
            if (t.GetInterface("IMyPluginInterface", true))
            {
               // we now have a potential plugin type that implements required functionality
            }
        }
    }
}

最后,.NET 3.5支持插件模型(System.AddIn),还可以查看Microsoft发布的托管扩展性框架,该框架允许开发人员为插件模型构建简单的可组合插件()

,我将从方法中查看
Activator.CreateInstance
Activator.CreateInstanceFrom,甚至可以查看
Assembly.LoadFrom
。这些方法允许您从“传统”输出目录以外的目录(
bin、debug、release
)中的程序集加载类型

强制
Type.GetType
查找“插件”程序集实际上取决于您如何修改加载程序搜索程序集的策略。例如,您可以设置
AppDomain.PrivateBinPath
属性来更改加载程序将查找引用程序集的子目录

关于第一点“添加对插件项目的引用”。好吧,这将使一个处于一个困难的境地,阻止将来的可扩展性。如果我想制作一个新插件呢?哎哟,现在你没有引用它,所以我想我的插件不会工作了?这就是为什么需要另一种方法。我们将“探测”插件程序集


在一个
ICrypt crypto = Plugins.Service["Crypt"] as ICrypt;
if (crypto != null)
  crypto.Crypt(data, key, etc)
[Hookable]
public event TextChanged OnTextChanged;
//.....
if (OnTextChanged != null)
  OnTextChanged(ref myText);
[Hooks("OnTextChanged")]
public bool MyTextChanged(ref myText)
{
  myText = "Hello from the plugin";
  return true;
}