提问人:Matthew Stewart 提问时间:12/13/2013 最后编辑:Matthew Stewart 更新时间:12/18/2013 访问量:968
此命名空间冲突是由于 XAML 到 .NET 代码生成中的错误造成的吗?
Is this namespace collision due to a bug in the XAML to .NET code generation?
问:
下面我将介绍如何重现我收到的错误。它在 VS 2010、2012 和 2013 中的行为相同。正如我在下面指出的那样,将其分解为多个项目很重要。
重现错误的步骤:
创建解决方案。
创建一个名为 Common 的 C# 类库,其中包含一个名为 Handler.cs 的文件:
using System; namespace Common { public delegate void Handler(object sender, EventArgs args); }
创建一个名为 MyControlLibrary 的 WPF 用户控件库项目,并引用 Common。在其中,创建一个名为 MyControl.xaml 的用户控件。
MyControl.xaml:
<UserControl x:Class="ControlNamespace.MyControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> </Grid> </UserControl>
MyControl.xaml.cs:
using System.Windows.Controls; using Common; namespace ControlNamespace { public partial class MyControl : UserControl { public MyControl() { InitializeComponent(); } public event Handler MyEvent; } }
创建一个名为 MyWpfApplication 的 WPF 应用程序项目,并引用 Common 和 MyControlLibrary。在其中,创建 WindowNamespace.Common.cs 以及一个名为 MyWindow.xaml 的窗口。
WindowNamespace.Common.cs:
namespace WindowNamespace.Common { }
MyWindow.xaml:
<Window x:Class="WindowNamespace.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:c="clr-namespace:ControlNamespace;assembly=WpfControlLibrary1" Title="MyWindow" Height="300" Width="300"> <Grid> <c:MyControl MyEvent="MyControl_MyEvent" /> </Grid> </Window>
MyWindow.xaml.cs:
using System; using System.Windows; namespace WindowNamespace { public partial class MyWindow : Window { public MyWindow() { InitializeComponent(); } void MyControl_MyEvent(object sender, EventArgs args) { } } }
生成解决方案。
您应收到以下错误,指向 MyWindow.xaml 的第 7 行:
类型或命名空间名称“Handler”在命名空间中不存在 “WindowNamespace.Common”(是否缺少程序集引用?
如果打开为 MyWindow.xaml 生成的 .g.i.cs 文件,则应在 IComponentConnector.Connect 方法中看到以下内容:
#line 7 "..\..\MyWindow.xaml"
((ControlNamespace.MyControl)(target)).MyEvent += new Common.Handler(this.MyControl_MyEvent);
问题的根源是它试图在 WindowNamespace 中查找 Common.Handler。这可以通过将其生成为以下方式来解决:
#line 7 "..\..\MyWindow.xaml"
((ControlNamespace.MyControl)(target)).MyEvent += new global::Common.Handler(this.MyControl_MyEvent);
或者通过在文件顶部添加 use:
using Common;
...
#line 7 "..\..\MyWindow.xaml"
((ControlNamespace.MyControl)(target)).MyEvent += new Handler(this.MyControl_MyEvent);
请注意,如果所有这些源文件都捆绑到单个项目中,则错误会消失,因为 .g.i.cs 文件的生成方式不同(即它不会显式将处理程序添加到事件中)。
这实际上是 XAML->.NET 翻译中的错误,还是我做错了什么?
答:
如果在 MyWpfApplication 的 WindowNamespace.Common 命名空间声明中重新声明 Handler 委托并尝试编译,则会出现什么情况:
Error 1 Cannot implicitly convert type 'WindowNamespace.Common.Handler' to 'Common.Handler' c:\Dev\YourSolution\MyWpfApplication\MyWindow.xaml 7 63 MyWpfApplication
Common 项目声明一个名为“Common”的全局命名空间,您的控件库也在使用该命名空间。但是,当应用程序显式声明“WindowNamespace.Common”时,它会创建一个本地命名空间,而该命名空间恰好与父控件所在的命名空间相同。这实际上会产生编译器错误 CS0433 的 Visual Studio 文档中描述的歧义问题。
将 MyWpfApplication 中的通用命名空间声明更改为“通用”,问题将消失。
评论