C# 如何从XAML中的CLR命名空间映射类型,而不是从它所在的程序集映射类型';谁宣布的?

C# 如何从XAML中的CLR命名空间映射类型,而不是从它所在的程序集映射类型';谁宣布的?,c#,wpf,xaml,namespaces,C#,Wpf,Xaml,Namespaces,在XAML中,我想使用来自两个不同程序集的类型,每个程序集都有自己的名称空间。我不想在xmlns:=“属性中显式声明名称空间,而是想使用[XmlnsDefinition]程序集属性将URI映射到这些类型的名称空间 其中一个程序集本身与WPF无关,因此我希望避免它引用任何与WPF相关的程序集,尤其是System.Xaml.dll程序集,如果该程序集使用[XmlnsDefinition]属性,则需要该程序集 我有一个Visual Studio解决方案,其组织方式如下: Gu.Units.sln

在XAML中,我想使用来自两个不同程序集的类型,每个程序集都有自己的名称空间。我不想在
xmlns:=“
属性中显式声明名称空间,而是想使用
[XmlnsDefinition]
程序集属性将URI映射到这些类型的名称空间

其中一个程序集本身与WPF无关,因此我希望避免它引用任何与WPF相关的程序集,尤其是
System.Xaml.dll
程序集,如果该程序集使用
[XmlnsDefinition]
属性,则需要该程序集

我有一个Visual Studio解决方案,其组织方式如下:

Gu.Units.sln Gu.Units.csproj // no ref to System.Xaml here Gu.Units.Wpf.csproj // references Gu.Units and System.Xaml
<UserControl x:Class="Gu.Units.Wpf.Demo.Sample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:units="http://Gu.com/Units">
    <Label Content="{x:Static units:LengthUnit.Millimetres}" />
</UserControl>
public class LengthUnits : Gu.Units.LengthUnits { }
我尝试在XAML中使用它,如下所示:

Gu.Units.sln Gu.Units.csproj // no ref to System.Xaml here Gu.Units.Wpf.csproj // references Gu.Units and System.Xaml
<UserControl x:Class="Gu.Units.Wpf.Demo.Sample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:units="http://Gu.com/Units">
    <Label Content="{x:Static units:LengthUnit.Millimetres}" />
</UserControl>
public class LengthUnits : Gu.Units.LengthUnits { }

但是由于某种原因,名称空间
Gu.Units
似乎被忽略了。也就是说,它不包括在URI
http://Gu.com/Units
。相反,我得到:

命名空间“”中不存在名称“LengthUnit”

XAML中的显式命名空间声明——即具有
xmlns:units=“clr namespace:Gu.units;assembly=Gu.units”
——可以正常工作,但我也希望避免这种情况


有没有一种方法可以让我的
Gu.Units.Wpf.dll
程序集提供必要的
[XmlnsDefinition]
属性来从
Gu.Units.dll
程序集映射名称空间,这样后者本身就不需要对
System.Xaml.dll
,也没有任何特定于XAML的代码?

如果我理解正确,您的问题可以归结为:

拥有
xmlns:units=“clr namespace:Gu.units;assembly=Gu.units”
很好,但这正是我试图避免的

有办法做到这一点吗

答案是:不,没有任何方法可以避免声明一些XML名称空间前缀

  • [xmlnprefix]
    属性对手动编写的XAML没有影响。也就是说,它不会在XAML的作用域中引入xmlns前缀。它只是XAML编写工具可以检索的一个标记,这样,当它们自动生成XAML声明时,就可以选择要使用的xmlns前缀。例如,如果使用VS Designer从引用的库中添加新对象,它可以在该库中查找,以了解在将对象添加到XAML时,它需要将适当的
    xmlns:
    属性添加到外部容器元素,并在添加对象的XAML中使用指定的前缀。

  • 这些属性都不会对在指定属性的同一程序集中编写的XAML产生任何影响。这些属性仅在完全编译的程序集中有用,当然,在编译程序集中的XAML之前,您不会得到这些属性。因此XAML无法使用这些属性。

  • 当在包含当前正在编辑的XAML的程序集引用的程序集中指定时,将保留
    [XmlnsDefinition]
    属性。在这种情况下,该属性很有用,但仍然不允许您放弃
    xmlns:
    属性声明。相反,它允许您映射URI(例如
    http://Gu.com/Units
    )到一个或多个CLR命名空间。这样,单个
    xmlns:
    prefix属性声明可以a)引用多个CLR名称空间,而b)这样做时,编写的XAML不必实际指定任何CLR名称空间(即,它封装程序集引用的托管代码方面,将其隐藏在URI后面).

    这样,您就可以编写
    xmlns:units=“clr namespace:Gu.units;assembly=Gu.units”
    ,而不是编写
    xmlns:units=”http://Gu.com/Units“
    这将允许
    units
    xmlns前缀限定附加到
    http://Gu.com/Units
    URI通过
    [XmlnsDefinition]
    属性。

    但是您仍然必须声明XML名称空间前缀,只是声明的形式与其他情况下需要的不同

  • 注意:当多个程序集使用
    [XmlnsDefinition]
    attribute要在彼此相同的URI中声明CLR命名空间,所有命名空间都由引用所有这些程序集的XAML中的URI引用。您可以利用此功能将自己库的命名空间与预期已在XAML中引用的URI的命名空间连接起来(例如
    http://schemas.microsoft.com/winfx/2006/xaml/presentation

    只要编写工具在XAML中发出的
    xmlns:
    属性中实际使用了该URI,这就“解决了”您正在询问的问题。但是将您自己的程序集名称空间与框架中预先存在的程序集名称空间混为一谈是一种黑客行为,也是不明智的。即使没有类型名称冲突,这仍然是一种糟糕的做法,当然,如果存在类型名称冲突,可能会导致严重的问题


    编辑:

    根据您的评论:

    我试图解决的问题是将Gu.Units加入到中,而不添加对System.Xaml for Gu.Units的引用

    发件人:

    将一个或多个XmlnsDefinitionAttribute属性应用于程序集,以便识别程序集中用于XAML的类型

    也就是说,您只能使用
    [XmlnsDefinition]
    来映射给定命名空间中的类型,这些命名空间实际上是在指定属性本身的同一程序集中声明的

    该属性包含一个
    AssemblyName
    属性,该属性似乎表示您可以包含来自其他程序集的类型。这是文档的自然读取,可能是使用该属性的目的