神秘的名称分辨率分辨率与SDK风格的C#项目之间存在差异

发布于 2025-01-30 12:54:54 字数 1609 浏览 4 评论 0 原文

我在尝试将.NET 4.6.1项目转换为新的SDK风格的项目格式时遇到了这个令人困惑的名称分辨率问题。我能够创建一个最小的repro解决方案 legacyvssdkstyleprojectnameresolution ,它在github上在此处:

解决方案包含:

  • 3个遗产项目针对.NET框架4.6.1居住在“传统” solution's solution's solution's solution's solution folder中;项目名称以“遗产”开头)。
  • 3个位于“ SDK”解决方案文件夹中的SDK式项目。项目名称以“ SDK。”开头。

(请原谅我非直觉的汇编 /名称 /类名称 - 我无法使用原始名称,也无法设计更可行的东西)。

依赖项如下所示:

lagacy.common.configuration project成功编译了 bundle 类声明:

using Legacy.Common.Data;

namespace Legacy.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

但是 sdk.common.configuration.configuration 产生编译错误 cs0118 ('Person'是一个名称空间,但像一种类型一样使用):

using Sdk.Common.Data;

namespace Sdk.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

任何人都可以解释一下,为什么 sdk.common.common.configuration中的C#编译器 Project project project solesolve person >将符号错误键入命名空间 sdk.common.common.person ,但在 Legacy.common.common.configuration 中,它将其正确解析到 legacy.common.data.person 类?

I encountered this confusing names-resolution problem while trying to convert legacy solution with .NET 4.6.1 projects to the new SDK-style project formats. I was able to create a minimal repro solution LegacyVsSdkStyleProjectNameResolution, which is on GitHub here:

https://github.com/PaloMraz/LegacyVsSdkStyleProjectNameResolution.git

The solution contains:

  • 3 legacy projects targeting .NET Framework 4.6.1 residing in the „Legacy“ solution folder; the project names start with „Legacy.“).
  • 3 SDK-style projects targeting .NET residing in the „Sdk“ solution folder; the project names start with „Sdk.“.

(Please forgive me the non-intuitive assembly / namespace / class names – I could not use the original names and was not able to devise something more feasible).

The dependencies are shown in this image:

CodeMap

The problem is, the Legacy.Common.Configuration project successfuly compiles with this Bundle class declaration:

using Legacy.Common.Data;

namespace Legacy.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

But the Sdk.Common.Configuration produces compilation error CS0118 ('Person' is a namespace but is used like a type):

using Sdk.Common.Data;

namespace Sdk.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

Can anybody please explain, why the C# compiler in the Sdk.Common.Configuration project resolves the Person type symbol incorrectly to namespace Sdk.Common.Person, but in the Legacy.Common.Configuration it resolves it correctly to Legacy.Common.Data.Person class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

书信已泛黄 2025-02-06 12:54:54

在SDK风格的项目中,一个项目将自动继承其依赖性所依赖的所有内容。在旧版项目中,必须手动完成,工具将明确的引用插入了对新依赖依赖的所有事物的明确引用。

因此,在您的SDK风格项目中,sdk.common.configuration继承了对sdk.common.person.management的引用,它是因为它引用了sdk.common.data。


sdk.common.person.management定义命名空间SDK.COMMON.PERSON:

namespace Sdk.Common.Person.Management
{
  ...
}

while sdk.common.data定义了类SDK.Common.data.person。:SDK.Common.Configuration,

namespace Sdk.Common.Data
{
  public class Person
  {
  }
}

进行此操作。

using Sdk.Common.Data;

namespace Sdk.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

然后 sdk.common.configuration (and sdk.common和sdk) person 之前,它考虑使用。它找到 sdk.common.person 是一个名称空间,并且因为使用名称空间作为类型而抱怨。

如果您在名称空间内使用使用,则此订单翻转,并且编译器将搜索 sdk.common.data first ,并找到<代码> sdk.common.data.person 类:

namespace Sdk.Common.Configuration
{
  using Sdk.Common.Data;

  public class Bundle
  {
    public Person Person { get; set; }
  }
}

有关详细信息


至于如何解决此问题,首先不要定义具有相同名称的类和名称空间。如果无法避免这种情况,则可以使用来更改的位置,如上所述,或使用 Person 类的完全合格名称。

如果您想镜像sdk.common.data的遗留行为,而不是由sdk.common.configuration继承,请使用 privateasserts =“ all” on project> projectReferference ,其中包括包括sdk.common.person.management。

<ProjectReference Include="..\Sdk.Common.Person.Management\Sdk.Common.Person.Management.csproj" PrivateAssets="All" />

这指出sdk.common.person.management是一种私人依赖性,它并非由引用sdk.common.data的任何内容继承。

In SDK-style projects, a project will automatically inherit all of the things that its dependencies depend on. In legacy projects this had to be done manually, with the tooling inserting explicit references to all of the things that a new dependency depended on.

So in your SDK-style project, Sdk.Common.Configuration is inheriting a reference to Sdk.Common.Person.Management, by virtue of the fact that it references Sdk.Common.Data.


Sdk.Common.Person.Management defines the namespace Sdk.Common.Person:

namespace Sdk.Common.Person.Management
{
  ...
}

While Sdk.Common.Data defines the class Sdk.Common.Data.Person.:

namespace Sdk.Common.Data
{
  public class Person
  {
  }
}

Sdk.Common.Configuration then does this:

using Sdk.Common.Data;

namespace Sdk.Common.Configuration
{
  public class Bundle
  {
    public Person Person { get; set; }
  }
}

There, the compiler searches the namespace Sdk.Common.Configuration (and Sdk.Common, and Sdk) for Person before it considers that using. It finds Sdk.Common.Person which is a namespace, and complains because you're using a namespace as a type.

If you include the using inside the namespace, this order flips, and the compiler will search Sdk.Common.Data first, and find the Sdk.Common.Data.Person class:

namespace Sdk.Common.Configuration
{
  using Sdk.Common.Data;

  public class Bundle
  {
    public Person Person { get; set; }
  }
}

See this answer for details.


As for how to solve this, first off don't define a class and a namespace with the same name. If you can't avoid this, you can either change the location of the using as shown above, or use the fully-qualified name of the Person class.

If you want to mirror the legacy behaviour of Sdk.Common.Data's references not being inherited by Sdk.Common.Configuration, use PrivateAsserts="All" on the ProjectReference which includes Sdk.Common.Person.Management.

<ProjectReference Include="..\Sdk.Common.Person.Management\Sdk.Common.Person.Management.csproj" PrivateAssets="All" />

This states that Sdk.Common.Person.Management is a private dependency, which isn't inherited by anything which references Sdk.Common.Data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文