这个命名空间冲突是由于 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 代码生成中的错误吗?的主要内容,如果未能解决你的问题,请参考以下文章

XAML 中的命名空间错误中不存在该名称

如何避免javascript命名空间冲突?

更改 WPF 项目模板的命名空间

C# cmake 构建中的 XAML 文件冲突

一个wpf命名空间问题

WPF使用其它的命名空间(宝典1)