您如何使基础架构代码仅在命名空间中可见?

Posted

技术标签:

【中文标题】您如何使基础架构代码仅在命名空间中可见?【英文标题】:How do you make infrastructure code only visible in namespace? 【发布时间】:2012-07-18 11:37:28 【问题描述】:

我有一个 Shutting-Yard 算法的实现,我正试图将它清晰地集成到我们的框架中。目前,我将它们全部打包到一个具有简单公共接口的类中。

namespace MathematicalParser 
  public class ExpressionParser 
    public ExpressionParser(string expression, List<string> variables);
    public double GetNumericValue(Dictionary<string,double> variableValues);
  

在这个类里面有很多帮助类、帮助枚举、静态变量等来映射不同的名字到函数。所有这些都是私有的,因此图书馆的用户无需担心。

为了提高代码的可维护性,我试图将逻辑上不相关的代码分离到它们自己的类中,但是这些类在 ExpressionParser 之外没有任何意义,所以我想将它们的可见性限制为命名空间 MathematicalParser(仅包含 ExpressionParser)。

如何在 c# 中最好地实现这一点,internal 关键字仅适用于程序集,而 private 不能在命名空间中使用。

【问题讨论】:

internal 有什么问题?您的程序集是否如此庞大以至于您不能相信其他开发人员不会尝试使用它们?命名空间的全部意义在于将类型组合在一起,因此不应混淆帮助类的用途。 @Joe 信任和信任,当他们尝试使用 ExpressionParser 时,我宁愿不要将他们暴露给不需要的类。正如我现在写的那样,公共接口很棒,所有的基础设施都隐藏在类中。我只是希望在不更改接口的情况下将代码拆分为逻辑一致的可维护块。 在这种情况下,我发布了一个可能有用的答案,这是我唯一能想到的。 Namespace only class visibility in C#/.NET? 的可能重复项 【参考方案1】:

我不会这样做(与 Joe 观点相同),但这是从 Lopina 的回答中得出的另一个解决方案:nested classes + partial classes

PublicClass.cs:

namespace MyNamespace

    public partial class PublicClass
    
        public int ReturnSomeStuff()
        
            MyHelperClass1 tmp = new MyHelperClass1();
            MyHelperClass2 tmp2 = new MyHelperClass2();

            return tmp.GetValue1() + tmp2.GetValue2();
        
    

PrivateClass1.cs:

namespace MyNamespace

    public partial class PublicClass
    
        private class MyHelperClass1
        
            public int GetValue1()
            
                return 5;
            
        
    

PrivateClass2.cs:

namespace MyNamespace

    public partial class PublicClass
    
        private class MyHelperClass2
        
            public int GetValue2()
            
                return 10;
            
        
    

程序.cs:

public class Program

    private static void Main(string[] args)
    
        PublicClass tmp = new PublicClass();

        MyHelperClass2 zz;  // Can't access MyHelperClass2 here cause it's private

        Console.WriteLine(tmp.ReturnSomeStuff());
        Console.ReadLine();
    

如您所见,您的不同帮助类在物理上被分隔在不同的文件中(也许它会帮助您维护代码)。而且你不能直接访问它们,它们是 PublicClass 私有的。

【讨论】:

这是一个非常有用的答案。它允许我拆分代码并从每个逻辑单元访问我的解析器定义的静态变量,而不会污染命名空间。【参考方案2】:

您是否尝试过使用私有嵌套类? 看这里:Private inner classes in C# - why aren't they used more often?

【讨论】:

我可能会误解你,但我相信现在是这样写的。我希望维护私有内部类(即非公共基础设施代码)的功能,同时将代码拆分为可维护的块。其中一些类非常大,如果实现中存在错误,它们本身可能需要更新。 啊,我明白了。您要声明和使用作为单独编译单元的私有类吗?【参考方案3】:

如果您真的很想这样做(根据我对原始问题的评论),您可以将所有帮助程序类放入一个程序集中并将它们设为内部,这样它们就可以有效地被禁止使用。然后制作第二个程序集,即您让人们使用的程序集,并将“公共”类和方法放入第二个程序集中。然后使用InternalsVisibleTo 允许您的“公共”程序集使用其他“私有”程序集的帮助程序类和方法。

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

这确实意味着您必须强制使用您的库的人在与包含您的“公共”库代码的程序集不同的程序集中工作。我认为根据您的问题,您是说他们在同一个程序集中工作,在这种情况下,您必须将“公共”库分离到不同的程序集中。如果你这样做了,那么只需将方法设置为内部并将它们放在同一个程序集中就可以完成这项工作。

如果您采用两个组件的路线,并且您的同事正在处理同一个组件,那么至少在引用另一个组件时存在额外的“步骤”,这可能会阻止他们使用它。

如果 还不够……我不知道,写一个 WCF 网络服务并解决它*。

*那是讽刺

【讨论】:

以上是关于您如何使基础架构代码仅在命名空间中可见?的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖包命名空间中的不可见函数?

如何使百里香弹簧安全命名空间可用?

C ++:使类及其某些数据成员仅在命名空间中可用

如何在 Python 中创建命名空间包?

JavaWeb项目前端规范(采用命名空间使js深度解耦合)

命名空间和程序集