这个命名空间冲突是由于 XAML 到 .NET 代码生成中的错误吗?
Posted
技术标签:
【中文标题】这个命名空间冲突是由于 XAML 到 .NET 代码生成中的错误吗?【英文标题】:Is this namespace collision due to a bug in the XAML to .NET code generation? 【发布时间】:2013-12-31 18:06:52 【问题描述】:下面我将描述如何重现我收到的错误。它在 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 行:
命名空间中不存在类型或命名空间名称“处理程序” '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);
或者通过在文件顶部添加 using:
using Common;
...
#line 7 "..\..\MyWindow.xaml"
((ControlNamespace.MyControl)(target)).MyEvent += new Handler(this.MyControl_MyEvent);
请注意,如果将所有这些源文件捆绑到一个项目中,错误就会消失,因为 .g.i.cs 文件的生成方式不同(即它没有明确地将处理程序添加到事件中)。
这实际上是 XAML->.NET 翻译中的错误,还是我做错了什么?
【问题讨论】:
感谢您努力重现此问题。太糟糕了,还没有任何解决方案。似乎一些 clr-namespace:... 调整以允许命名空间中的 global: 可以解决问题。 【参考方案1】:如果您在 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”时,它会创建一个本地命名空间,该命名空间恰好与父控件所在的命名空间相同。这有效地产生了Visual Studio documentation for Compiler Error CS0433 中描述的歧义问题。
将 MyWpfApplication 中的公共命名空间声明更改为“Common”,问题就会消失。
【讨论】:
您对命名空间冲突的性质是正确的,它假设 Common 是指存在于当前命名空间中的那个,而不是全局 Common。但是,共享相同名称的两个命名空间是……常见的,C# 提供了解决这些冲突的机制,而无需重命名其中一个。在这种情况下根本无法使用这些机制,因为我不是编写 C# 的人,除非 XAML 公开了一种方法。 我假设您已经考虑并拒绝了别名?您可能必须提供更多详细信息,然后才能控制哪些部分。无论哪种方式,我都怀疑这算作编译器错误,它正在使用您提供的名称空间。你能不将事件绑定到 ICommand 或其他东西并解决代码中的冲突吗? 我不清楚别名在这里有什么帮助;你能澄清一下吗?我没有指定无法解析的类型,因此我没有机会提供命名空间别名。这仅在为基于 XAML 事件绑定分配事件处理程序而生成的代码中指定。以上是关于这个命名空间冲突是由于 XAML 到 .NET 代码生成中的错误吗?的主要内容,如果未能解决你的问题,请参考以下文章