Visual Studio在哪里查找程序集?

6

我有一个框架,其中包含许多基础类,可以派生出很多应用程序。在这些类中,有一个 System.Windows.Forms.Panel 的子类,我为它编写了自己的设计器。在使用 Visual Studio 2005 时一切都正常,但当我尝试转移到 VS2010 时出现了问题。以下是我正在做的简化版:

我有一个名为 CoreClasses 的项目,其中包含一个接口和两个类:

public interface IConf
{
    string foo { get; set; }
    void InitFoo();
}

public class SimpleClass
{
    public string foo;
}

public class ConfLoader
{
    public static IConf LoadConf()
    {
        AssemblyName anAssemblyName = new AssemblyName("ConfClasses");
        Assembly anAssembly = Assembly.Load(anAssemblyName);
        IConf result = (IConf)anAssembly.CreateInstance("ConfClasses.ConfClass");
        result.InitFoo();
        return result;
    }
}

然后有一个名为ConfClasses的项目,引用了CoreClasses,并且仅包含一个实现IConf接口的类:
public class ConfClass : IConf
{
    public SimpleClass confVal;

    public string foo
    {
        get { return confVal.foo; }
        set { confVal.foo = value; }
    }

    public void InitFoo()
    {
        confVal = new SimpleClass();
        confVal.foo = "bar";
    }
}

最后,有一个控件项目,只引用了CoreClasses,并包含Panel的子类和相关的设计器:

[Designer("MyControls.Design.SimplePanelDesigner", typeof(IRootDesigner))]
public class SimplePanel : Panel
{
    public SimpleClass dummy = new SimpleClass();
}

public class SimplePanelDesigner : DocumentDesigner
{
    public IConf DesignerConf;

    public SimplePanelDesigner()
        : base()
    {
        DesignerConf = ConfLoader.LoadConf();
    }
}

现在我创建了另一个解决方案,它引用了所有这些dll,并包含SimplePanel的一个空子类。当我在SolutionExplorer中双击此类时,将执行SimplePanelDesigner的构造函数并调用ConfLoader的LoadConf方法。这意味着ConfClasses.dll被动态加载,并创建了ConfClass的实例。一切都很好,但是当调用InitFoo时,会引发以下异常:无法加载文件或程序集“CoreClasses,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”或其某个依赖项。系统找不到指定的文件。更麻烦的是,实际上在这个例子中并没有引发异常,但这正是我的真实应用程序正在执行的指令类型,以及我得到的异常。我不知道这里发生了什么。VS正在执行位于CoreClasses中的方法。为什么它要再次加载它?而且它在哪里寻找它?我也检查了当前的AppDomain,但它已经在它的加载程序集中有了CoreClasses,并且似乎没有改变。只是为了添加更多细节,每个项目都在一个共同的文件夹中构建(而不是项目文件夹中通常的obj / debug文件夹),并且在开始测试时PC上没有我的dll的其他副本。然后,在AppData \ Local \ Microsoft \ VisualStudio \ 10.0 \ ProjectAssemblies文件夹的一系列文件夹中复制了所有引用的dll的副本,并且当执行Assembly.Load时,这似乎是VS寻找程序集的地方,我可以在那里找到CoreClasses的一个副本。我尝试清理所有文件夹,重新构建所有内容,并在每种组合中保持不同的解决方案打开/关闭,但没有任何改进。

编辑:
正如GranMasterFlush建议的那样,这是异常生成的FusionLog:
=== Pre-bind state information ===
LOG: User = FCDB\fc0107
LOG: DisplayName = XEngine.Core, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).

编辑2

补充一些信息,我查看了由我的简单示例生成的融合日志,并发现在尝试加载CoreClasses时生成了完全相同的日志,但VisualStudio以某种方式找到了应对措施。


我使用 procmon 来验证它所抱怨的文件是否实际上存在于 AppData\Local\Microsoft\VisualStudio\11.0\ProjectAssemblies\<some temporary name> 中。最终发现是因为我的自定义控件试图启动一个线程(DesignMode 属性不起作用,请参见此解决方案)。我通过研究关于如何调试设计时行为的这篇文章找到了这个问题。 - darda
2个回答

5
我刚刚发现发生了什么。简单示例和实际情况的区别在于涉及到一个AddIn。尽管这是一个很长的故事,但这就是事情的真相。
正如您从代码示例中看到的那样,我通过反射加载ConfClasses dll,以避免添加对它的引用。这在运行时是可以接受的,但设计师抱怨说无法将IConf转换为IConf。这是因为当设计师启动时,CoreClasses.dll从AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies中加载,但ConfClasses.dll从我的bin文件夹中加载,以及其引用,所以有两个版本的CoreClasses.dll和不同版本的IConf。
为了绕过这个问题,我开发了一个AddIn,在设计时间使用Assembly.Load加载一个程序集时,向该程序集添加一个引用,然后在最后一个设计器窗口关闭时清除引用。
VS2005一切正常,但使用ProcMon.exe,我发现VS2010添加了一个新的文件夹,AddIns在其中查找程序集:Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\CommonExtensions\DataDesign
我将我的程序集复制到那里,一切都恢复正常了。现在只需要找到一种手动添加东西的方法。

2

我所有的项目都将一个文件夹设置为输出路径,因此所有的dll文件都在同一个文件夹中,这显然不是Visual Studio的文件夹。这些程序集并不是从这个文件夹加载的,而是从一个副本加载的,该副本位于AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies的子文件夹中,我可以在那里找到它们。 - Francesco Baruchelli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接