c#解决方案中的命名空间和文件夹结构:应该如何组织磁盘上的文件夹?

问题描述 投票:15回答:8

首先,我们同意名称空间应与文件夹结构匹配,并且每种语言的人工制品都应位于其自己的文件中。

(请参阅Should the folders in a solution match the namespace?

下一个问题是文件夹应如何实际在磁盘上组织。假设我在A.B.C名称空间中具有ClassC,在A.B.C.D名称空间中具有ClassD。我们还假设每个命名空间都内置于自己的程序集(项目)中,并且按照公认的最佳做法,命名空间从右到左具有依赖性(A.B.C.D可以依赖于A.B.C,而A.B.C可以依赖于A.B,而A.B可以依赖于A)。我感谢每个名称空间不必位于单独的程序集中,但通常情况下,我们将在单独的程序集中包含一些名称空间,我的示例对此进行了说明。

[我至少可以看到两种创建文件夹树的方法-我将其称为“嵌套文件夹”和“平面文件夹”:

1-嵌套文件夹:

A--A.csproj--B---- A.B.csproj - - C------ A.B.C.csproj------ classC.cs------ D-------- A.B.C.D.csproj-------- classD.cs

OR

2 –平面文件夹:

A--A.csprojA.B--A.B.csproj公元前--A.B.C.csproj--classC.csA B C D-A.B.C.D.csproj--classD.cs

您将看到我已经做了一些假设:

  • 每个项目文件都有一个基于名称空间的完全限定名称(FQN)。
  • 每个类文件使用非FQN

嵌套的文件夹似乎更自然(我们都喜欢层次结构),但是在大型解决方案中可能很难导航:

当您在VS中查看解决方案时,它显示的是项目的平面列表,而不是嵌套视图。这看起来更像是“平面文件夹”,因此组织磁盘上的文件夹以匹配VS中的视图可能有好处。

[如果查看磁盘上的每个文件夹,您将看到该项目的文件夹伪像以及名称空间的子文件夹:以C为例:

C--bin--D--obj-物业--A.B.C.csproj--classC.cs

根据D的全名,可能不是很明显D是C名称空间中的名称空间文件夹而不是组织文件夹。

我知道我们从.NET(八,九年前)和Java的第一天开始就有文件夹和名称空间,但是就个人而言,我们似乎并未就最佳实践项目组织达成共识适用于大型解决方案。我真的很想知道大家的想法。

谢谢迈克尔

c# namespaces solution
8个回答
8
投票

我使用固定方式。我发现嵌套层次结构很难维护。我将我的项目分为几个解决方案,同时考虑到最大的可重用性和交叉引用,并始终感到满意。示例(项目缩进):

CompanyName
  CompanyName.Core
    Class1
    Struct2
    Enum3
  CompanyName.Data
  CompanyName.Web

CompanyName.Projects
  CompanyName.Projects.Core

CompanyName.Projects.ProjectX
  CompanyName.Projects.ProjectX.Core
  CompanyName.Projects.ProjectX.Website
  CompanyName.Projects.ProjectX.ToolY

等等

编辑:删除废话


5
投票

我不是嵌套项目的忠实拥护者,因为它会将项目埋在结构内部,如果您需要在另一个应用程序中重用该项目,那么您应该怎么做,复制/粘贴代码?我喜欢遵循某种平面结构,但按名称空间组织。

这是我的方法:

- DataHelpers\
---Factory\
---DataAccess\
---...
- Components\
--- EmailProcessor\
--- ErrorLogger\
- Desktop\
--- WindowsApp1\
- Services\
--- WindowsService1\
--- WindowsService2\
- WebApps\
--- WebApp1\
--- WebApp2\

现在,在我拥有的每个主要应用程序中,例如:

- WindowsService1\
--- WindowsService1\ (this contains all *.cs, bin, obj, etc and .csproj file)
--- Solution\ (this contains the .sln file where you link to other projects like ErrorLogger, etc)

我希望这很有道理!


3
投票

“首先,我们同意名称空间应与文件夹结构匹配,并且每种语言工件都应位于其自己的文件中。”

很有趣,这就是程序包在Java中的工作方式。我一直认为断开名称空间和目录结构之间的链接被视为C#引入的改进之一。那不是真的吗(请原谅我的无知,我是Java人。)


3
投票

我一直做嵌套的层次结构。这使得在向现有解决方案中添加新项目的位置变得显而易见,并使名称空间在磁盘上井井有条。这也使命名空间与项目之间的偏差更加明显。


2
投票

如果使用嵌套项目,则可能会遇到Windows MaxPath问题。对于使用嵌套结构而言,这是一个巨大的突破。试想一下,在开发项目中途遇到这个小Gem,必须用3个字母的缩写来命名VS项目,以免打到MaxPath。一个MS错误,最终激发了程序集名称的灵感。真是个笑话。全面使用平面结构要好得多。

   -SouceControlFolderName
     -Project1
       -Src
         -Main
           -Company.Project1.AppName
             *Company.Project1.AppName.sln
             *Company.Project1.AppName.Tests.sln
             -Company.Project1.AppName.Common
             -Company.Project1.AppName.Common.Tests
             -Company.Project1.AppName.Entities
             -Company.Project1.AppName.Entities.Tests
             -Company.Project1.AppName.Security
             -Company.Project1.AppName.Security.Tests
             -etc.

您可以为测试项目或如上所述创建一个单独的目录,并将它们放在一起,在添加到源代码控制(例如Subversion)中时,该目录更易于管理(TFS在很多方面都更好,因为它需要与Explorer集成,而不仅仅是VS整合和适当的离线故事)


0
投票

我认为您需要定义一个不再使用统一方法的截止点。例如,如果您在一个较小的项目中具有典型的3层体系结构,那么在外部级别具有3个项目就没有问题。但是,如果只有几十个,则某种分组有助于分段功能,并使整个解决方案更易于理解。


0
投票

我更喜欢以项目为根的扁平结构。

  • MyCorp.Core
  • MyApp.Domain
  • MyApp.Data
  • MyApp.UI
  • MyApp.Test

在这些文件中,我有各种文件夹和名称空间。我只为可部署单元创建不同的程序集。小型应用程序甚至没有这种分隔。海事组织这使事情变得简单。如果我决定需要在其他地方使用我的代码,只要我遵循了良好的命名间隔惯例,就可以很容易地将它分成一个程序集。


0
投票

12年以来,在此问题上是否有任何确定的或最佳实践答案?

我想使用嵌套文件夹结构,但是鉴于您:

“同意名称空间应与文件夹结构匹配,并且每个语言伪像应该在其自己的文件中。“

项目A.B.C.csproj文件夹结构如何从其他命名空间扩展代码,例如:

  • 祖父母:A.csproj
  • 父:A.B.csproj
  • 外部命名空间
  • System.Linq
  • Microsoft.Extensions.Logging] >>也许像:

/A // namespace: A /B // namespace: A.B /C // namespace: A.B.C A.B.C.csproj ClassC.cs /_ // External Namespace root folder (underscore with no text) /System // namespace: System /Linq // namespace: System.Linq IQueryableExtensions.cs /Microsoft // namespace: Microsoft /Extensions // namespace: Microsoft.Extensions /Logging // namespace: Microsoft.Extensions.Logging ILoggerExtensions.cs /__A // namespace: A (Grand Parent folder (2 underscores for 2 levels up) ClassAExtensions.cs /B // namespace: A.B (Nested Parent folder) ClassBExtensionsNested.cs //Parent Namespace folder (1 underscore for 1 level up) /_B // namespace: A.B ClassBExtensions.cs /D // namespace: A.B.C.D (Child folder) ClassDExtensions.cs

以上试图证明:

    具有单独的下划线(_)且没有后面跟随文本的文件夹将替换为所有外部名称空间的空名称空间和新根。
  • 带下划线(__A)和(_B)的文件夹,后跟文本替换项,作为当前项目树/层次结构中的上一级。每个下划线1级
© www.soinside.com 2019 - 2024. All rights reserved.