【发布时间】:2011-12-15 17:31:51
【问题描述】:
我正在尝试开发一个使用插件的应用程序。我有一个用于主应用程序的项目,一个用于插件可以/必须使用的常见元素,以及一个用于测试插件的项目。主项目和测试插件项目都引用了公共元素。如果我将 Copy Local 设置为 true,那么我会得到三个公共元素的副本(当我有更多插件时情况会更糟),我认为这会扰乱反射。当主程序试图反映应用到测试插件中的类的自定义属性(共同定义)时,使用
Object[] attributes = pluginType.GetCustomAttributes(typeof(PluginAttribute), true);
我没有找到该属性,但是当我找到时:
Object[] attributes = pluginType.GetCustomAttributes(true);
属性出现在列表中。我猜这是因为主程序和测试插件从不同的程序集中获取 PluginAttribute,所以它们不会被视为同一事物。
解决方案似乎是关闭复制本地。但是,当我这样做时,我得到一个运行时错误,即程序找不到包含公共元素的程序集。如何告诉运行时在哪里寻找它?
任何帮助将不胜感激!
编辑:
好的,这里是场景的更多细节。
我在解决方案中有三个项目。一个是用于 dll 的,我们称它为 Common,我将其保留在 VS 为其选择的目录中,因此 dll 最终位于 ./Common/bin/Debug。 dll 包含所有插件都应实现的接口的定义:类似于
namespace Common
{
[ContractClass(typeof(PluginContract))]
public interface IPlugin
{
String Foo();
}
}
它还包含可应用于插件的属性类的定义,例如:
public class PluginAttribute: Attribute
{
public String Bar {get; protected set;}
public PluginAttribute(String bar)
{
this.Bar = bar;
}
}
下一个项目是主机,它是一个可执行文件。同样,它位于默认目录中,因此可执行文件位于./Host/bin/Debug 中。它在 ./Host/bin/Debug/Plugins 中搜索程序集,并使用反射在每个程序集中搜索实现 IPlugin 的类。如果是,那么我使用上面引用的代码来查看它是否设置了 PluginAttribute。
最终的项目是一个测试插件,我已将其构建为./Host/bin/Debug/Plugins。
namespace TestPlugin
{
[PluginAttribute("Test Class")]
public class TestClass: IPlugin
{
public string Foo()
{
return "Foo";
}
}
}
Host 可以在 TestPlugin 程序集中找到 TestClass,但我无法访问 PluginAttribute。我的猜测是因为我有三个Common.dll 副本,并且主机使用./Host/bin/Debug 中的副本存在问题,但TestClass 可能是使用@987654335 中的副本构建的@,一个物理上不同的 dll(这是否使它成为不同的程序集,或者它只是同一个 dll 的另一个副本?)所以为了跟进这个猜测,我尝试将 Copy Local 设置为 false,所以我只有一个 @987654336 的副本@在./Common/bin/Debug。这构建得很好,但给了我一个运行时错误,它无法加载 Common 程序集。
【问题讨论】:
-
对此唯一好的解释是您的 PluginAttribute 类出现在多个程序集中。你需要解决这个问题。将类移动到所有插件引用的单个程序集。
-
我怀疑您有两个 AppDomain 在不同的目录中解析,因此加载了它们自己的属性副本,或者您有一个行为不端的程序集解析器正在重新加载程序集。您能否提供有关如何加载其他程序集的更多信息?
-
您是否引用了这个“通用元素”程序集的不同版本?
-
Hans:这正是我想要做的。我的 Host 类和我的测试插件都引用了公共 dll,但是 Copy Local 会创建多个 dll,并且关闭 Copy Local 会给我一个运行时错误。
标签: c# .net reflection