提问人:Kevin VP 提问时间:12/2/2013 更新时间:4/19/2014 访问量:466
集会。。。内部和外部命名空间
Assembly ... internal & external namespacing
问:
这里有一个简单的问题。我有一个程序集被一些开发人员重用,它包含各种功能位,但在技术上被拆分为代表功能逻辑块的各种命名空间。
现在,它提供了尽可能少的公共命名空间。基本上,用户不应该知道(并且目前不知道)他们尝试使用的类正在使用哪个内部结构。
假设你有这个:
NS1的
- NS11型
- 111类
- 112类
- NS 扩展
- 扩展类 1
- NS12型
KSW公司
- ...
基本上,用户知道他们使用 FrameworkName.NS1 来实现有关 NS1 的一般功能。 现在,在这个简单的示例中,我将一个包含扩展方法的类放在子命名空间扩展中,因此基本上,如果最终用户尝试使用程序集,他必须实际知道 DLL 的内部结构才能知道扩展的存在(这是智能感知不会告诉您知道的示例之一)。
所以底线......现在我有了这个程序集,在内部(VS 项目)我像往常一样将项目划分为逻辑文件夹,但我不让命名空间跟随文件夹。这样一来,程序集就会被拆分为用户知道的逻辑块,而不必知道内部结构,也不需要知道扩展可以有单独的命名空间等等。
现在,就我个人而言,我希望我可以让我的代码命名空间遵循我的文件夹结构,但在编译时以某种方式将这些子命名空间映射到主命名空间。
是否有可能以某种方式实现这种“重定向”?
简单地说,我希望能够解决 NS1。NS11 中。Class111 公开称为 NS1。Class111 在组件外部,同时在组件内部仍保持适当的结构。
答:
如果您需要通过不同的命名空间提供对某些内部代码的第三方访问,我会将数据访问抽象到一个单独的程序集中(这取决于原始程序集),或者使用 Web 服务来提供您希望他们访问的功能子集。
你也许可以对每个类的属性做一些事情,尽管我想它会变得非常混乱,很快就会变得很混乱。
有几种方法可以考虑这一点。 我最初来自 VB.net 背景,最近来自 C#,我对这个话题有以下评论。
- VB 中不采用文件夹\命名空间约定。
- 您将如何解决代码版本控制和管理问题。
- 如果引入其他 c# 开发人员来补充你的团队,他们可能会发现很难理解命名空间/文件夹转移。
- 可以将父命名空间放在 csproj 属性中的应用程序“默认命名空间”下。这将允许您通过复制和粘贴继承或源代码管理文件夹或子项目在项目之间共享这些公共实用工具(文件夹)。这允许 NS1.扩展和 NS2。包含相同代码的扩展。
- 我不会担心过多地“隐藏”内部公司 API,除非它是一个特别敌对的技术环境。即使是“加密”方法也应使用适当的公钥/私钥基础结构,以使其在设计上安全。
- 如果你看一下大多数框架是如何分解那里的解决方案的,你会看到一系列项目,其中包括命名空间的所有代码,如“Core”、“Shared”、“Common”。这些开发人员中的大多数都非常聪明,所以如果这是他们做事的方式,我会遵循。
- 您是否考虑过将 nugget 部署到“共享网络文件夹”并设置所有开发人员将 VS 指向该位置?
- 最后,我发现扩展和帮助程序方法很快就会变得非常稳定,因此代码不会发生太大变化。我将它们推送到源代码管理 /library/MyBusinessName/NameOfService.1.0.0.0/ 中包含的文件夹。与 Nuget 包使用的文件夹结构相同,因此我知道何时使用我的核心基础公司代码或框架的版本。
- 最后,如果你要让你的代码沿着MVVM路径向下移动(流行),并且你看到依赖注入的价值,那么你将不得不包含许多“接口”来帮助测试你的通用共享代码,这在单独的DLL/项目中要容易得多。
就我个人而言,我曾与一个团队合作,该团队为他们在公司软件中引用的每件事导入了所有底层源代码,因此他们可以“更改”任何内容。归根结底,它创造了一个不神圣的构建复杂性水平,并在调试时吓跑了我的裤子。Nuget 提供了一个非常流行且非常流行的模型,我已将其用于公司“共享”代码。如果我需要“tweek”共享代码,我会在解决方案/项目中单独执行,测试它,部署它并使用源代码管理或 nugget 来复制文件。
这里有一个想法:创建供公众使用的包装类。它可能有点低效(尽管 JIT 可能会处理它),并且相对更难维护,但如果您担心您的公共 API(您应该担心),它可能是一个不错的选择。在大多数情况下,链接几个调用不会有任何问题,你会有一个与公共 API 相关的层,这可能会让你在门面后面犯一些罪(例如,为了性能而破坏一些好的软件设计规则)
您可以根据自己的喜好创建内部结构:
namespace Framework.Cool.Internal
{
internal class BeansWeWantToCook
{
internal bool Cook()
{
// cooking process
}
}
}
..然后,使用要公开的命名空间为内部功能创建一个公共包装器:
namespace Framework.Cool
{
public class Beans
{
// omitted code for brevity
public bool Cook()
{
return _beansWeWantToCook.Cook();
}
}
}
这将创建一个非常传统的结构,它不会让任何寻找浏览应用程序的类的人感到惊讶。
另一种选择是采用特定于项目的约定,例如将所有公共类保留在项目的根目录下。
BTW, I wouldn't do anything funny with compile or build time procedure. I think that would be too confusing especially for new comers.
评论
NS1.NS11.Class111
NS1.Class111
NS1.NS11