Fra*_*lli 6 c# visual-studio-2010 windows-forms-designer
我有一个框架,其中包含许多基类,可以派生它们来开发许多应用程序.在这些类中有一个System.Windows.Forms.Panel的子类,我为它编写了自己的设计器.Visual Studio 2005一切正常,但当我尝试迁移到VS2010时出现问题.这是我正在做的简化版本:
我有一个名为CoreClasse的项目,它包含一个接口和两个类:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后有一个项目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";
}
}
Run Code Online (Sandbox Code Playgroud)
最后有一个控件项目,它只引用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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我创建另一个引用所有这些dll的解决方案,并包含一个SimplePanel的空子类.当我在SolutionExplorer中双击此类时,将执行SimplePanelDesigner的构造函数并调用ConfLoader的方法LoadConf.这意味着ConfClasses.dll以dinamically方式加载,并创建一个ConfClass实例.到目前为止一切都很好,但是当调用InitFoo时会引发异常:
无法加载文件或程序集"CoreClasses,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null"或其依赖项之一.该系统找不到指定的文件.
为了使事情变得更难,在这个例子中实际上没有提出异常,但这正是我真正的应用程序正在执行的那种结构,以及我得到的异常.我还没有弄清楚这里发生了什么.VS正在执行CoreClasses中的IS方法.为什么要再次加载它?它在哪里寻找它?我也检查了当前的AppDomain,但它在其加载的程序集中有CoreClasses,它似乎没有改变.
只是为了添加更多细节,每个项目都构建在一个公共文件夹中(不是项目文件夹中常用的obj/debug文件夹),而且在我开始测试的那一刻,PC上没有其他的dll副本.然后,所有被引用的DLL的一个副本在一系列的应用程序数据\本地\微软\ VisualStudio的\我USERPROFILE 10.0\ProjectAssemblies文件夹中的文件夹就完成了,这似乎是VS正在寻找组件时Assembly.Load的地方执行,我可以在那里找到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).
Run Code Online (Sandbox Code Playgroud)
编辑2
只是为了添加一些信息,我看了一下我的简单例子生成的融合日志,发现在尝试加载CoreClasses时生成了完全相同的日志,但是VisualStudio找到了解决它的方法.
我刚刚知道发生了什么事。简单示例与真实示例之间的区别在于涉及一个 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 添加了一个新文件夹,插件在其中查找程序集:Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\CommonExtensions\DataDesign
我在那里复制了我的程序集一切又恢复正常了。现在只需找到一种手动添加内容的方法即可。