我能强制C#命名空间之间的依赖关系吗?

3

我可以限制一个特定命名空间的类不引用另一个特定命名空间的类吗?这两个命名空间存在于同一个 .NET 程序集中。

示例:

namespace LegacyCode
{
    class LegacyClass { ... }
}

namespace NewCode
{
    class NewClass {...}
}

我不希望'NewCode'的类能够引用'LegacyCode'中的类。

选项:

  1. 使用不同的程序集(使部署更加困难,构建时间更长)
  2. 使用像NDetect这样的工具(需要花费金钱!)

还有其他的想法吗?

5个回答

10
考虑使用Obsolete attribute标记类。这将导致在编译期间未被标记为“Obsolete”的任何代码生成警告。
在项目文件的“Build”选项卡上启用“将警告视为错误”设置,可以使此警告导致编译失败并显示错误。
编辑:
同意单独的程序集是促进淡化此代码的好策略。但这不会阻止人们引用它。过时属性清楚地表明该代码已经过时。
编辑#2:
感谢Dan Tao指出了过时属性的overloaded constructor。这意味着您可以强制执行是否应将某个内容的使用视为错误,而无需启用将警告视为错误。还有一个有用的选项,即指定一条消息,指示用户解决问题的方法。此消息会在编译期间在错误/警告中显示。

1
ObsoleteAttribute 类的一个重载 构造函数 接受一个 bool 参数,指定是否将对标记类的引用导致编译错误。 - Dan Tao
谢谢丹 - 我以前从没注意到过! - MPritchard

7

记录设计,与人交流,审核代码。不要试图用技术解决人类问题。(使用NDetect等工具可以提高审核效率)。

如果您真的需要设计更改的隔离性,请选择单独的程序集:这是预期的设计机制。但请确保您对接口和实现都有合理的版本控制方案。


原则上我认为你是正确的 - 这也是我们目前的解决方案(用于传达规则)。 但实际操作中,这并没有起作用。一个有经验的开发人员提交了一个破坏依赖关系的新类 - 审查者也错过了。这就是为什么我想要一种更严格的控制方式。 - GarethOwen
2
很高兴听到这个消息!我认为你不得不咬紧牙关,接受成本,要么以分离的程序集管理形式,要么以依赖性执行工具形式。 我不知道是否有任何免费替代NDepend(肯定没有它的功能集),但是破坏依赖关系一定会花费你的资金,特别是如果维护时间长达几年--提前投资以避免后来的技术债务听起来更可取。 - Pontus Gagge

3
我认为分离的程序集是唯一可能的解决方案。

3

微软使用System.ObsoleteAttribute属性来标记过时/遗留代码。该属性提供了一个ctor,用于创建编译器错误。不过,如果遗留类不太多,我会使用它。


我不知道过时属性 - 它听起来很好。但不幸的是,我们确实有很多遗留类 :( - GarethOwen
2
相信我 - 花一个下午复制和粘贴[Obsolete]是值得的。如果您的代码在文件夹中适当地布局,使所有过时的代码都在同一个文件夹中,则可以尝试在Visual Studio中使用正则表达式进行查找和替换。我假设您希望将此应用于类、枚举和结构体。 - MPritchard
老板对我们代码库中90%被标记为过时并不太满意。 - GarethOwen
我同意你的观点,MPritch。也许我会编写自己的自定义属性,它与“Obsolete”执行相同的操作,但名称更友好。 - GarethOwen
2
@GarethOwen:使用[Obsolete]的好处不就是编译器在引用代码中出现时会报告警告/错误吗?如果是这样,那么很遗憾,你自己编写的代码就不能起到这个作用了:https://dev59.com/r3VC5IYBdhLWcg3w4Vb6#154254。我真的很难理解标记过时代码有什么问题... - MPritchard
显示剩余4条评论

1

正如其他人所说,使用过时的属性(即使您必须重命名它)。

但是更进一步。尽快删除任何不再使用的遗留方法。这将防止有人以后使用它。您应该开始看到由于过时属性而导致的编译器警告随着时间的推移而减少。

您甚至可以将其作为每日一小时的测试,以消除尽可能多的编译器警告...也许您可以在下班后为每日获胜者买一杯啤酒(或软饮料..;)。


1
我们将其作为构建状态添加到了我们的TeamCity构建中。看到一个图表慢慢趋近于0是一件很不错的事情。 - MPritchard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接