我正在开发一个使用Depency Injection的项目。注册一组接口和类时,我需要指出这些接口和类所在的命名空间。
我不喜欢提供字符串常量,主要是因为它会影响可重构性。我不喜欢接受其中一个接口/类并获取它的命名空间。例如:
typeof(FoodStore.Fruits.IApple).Namespace
因为看起来很奇怪所有这些任意类型的名称都在徘徊(为什么选择IApple
而不是IOrange
?),只是为了分散代码的实际意义。根本没有明智的规则可供选择。
我提出了以下解决方案。
在我需要引用的每个命名空间中放置命名空间锚类:
namespace FoodStore.Fruits
{
/// <summary>
/// Serves as a type based reference to the namespace this class
/// is located in.
/// </summary>
public sealed class _NamespaceAnchor
{
}
}
现在我可以使用:
typeof(FoodStore.Fruits._NamespaceAnchor).Namespace
每当我重构命名空间时,我都不必担心DI注册。
虽然这个解决方案满足了问题的要求,但我仍然不高兴,因为现在我有这些丑陋的空类。我不能使它们internal
因为 - 显然 - 引用跨越组件。
我的问题是:有没有人知道更优雅的解决方案?
答案 0 :(得分:3)
不,没有更好的东西 - 据我所知,命名空间并不是CLR中真正的一流概念。是的,Type
允许您向它请求命名空间 - 但命名空间实际上是针对人而不是VM。
请注意,与Java不同,命名空间级别没有访问控制。我没有检查过,但是我怀疑没有特定的元数据令牌用于命名空间。
我无法想到在执行时会影响CLR的命名空间。显然它们会影响语言编译器 - 但同样,这也是为了人类的利益,因此我们可以分层次地组织类型,并避免在每一步都指定层次结构。
答案 1 :(得分:1)
我在这里担心命名空间(实际上只是类名的一部分)在你的应用程序中具有功能意义。如果后来的维护工程师移动了一些类,他们可能会在没有意识到的情况下无意中破坏喷射系统。错误在运行之前不会变得明显,并且可能需要一段时间才能跟踪。
在这种情况下,我更喜欢更明确的选择加入,例如使用属性。这是一种可能性:
public class TestInterfaceAttribute : Attribute { }
public interface IMyInjectableService { }
[TestInterface]
public class TestService : IMyInjectableService { }
public class RealService : IMyInjectableService { }
尽管如此,大多数DI框架已经具有某种形式的导出元数据(以帮助解决特定用例的正确依赖关系),或者以明确定义依赖关系解析的方式构建。