C# c中子命名空间的封装#

C# c中子命名空间的封装#,c#,namespaces,encapsulation,C#,Namespaces,Encapsulation,我有一个类库项目。在这个项目中,我有一些文件夹来分隔逻辑 假设我有一个DAL库,在DAL中我有IDAL、DALFactory和SQLServerDAL 现在,当我把DAL dll给其他程序员时,他可以使用所有的子dll。假设我不想让他使用SQLServerDal,而是其他的。如何封装SQLServerDAL,以便无人能意识到它的存在。 谢谢 编辑: 更具体地说: using DAL; // it can be written using DAL.IDAL; // it can be writte

我有一个类库项目。在这个项目中,我有一些文件夹来分隔逻辑

假设我有一个DAL库,在DAL中我有IDALDALFactorySQLServerDAL
现在,当我把DAL dll给其他程序员时,他可以使用所有的子dll。假设我不想让他使用SQLServerDal,而是其他的。如何封装SQLServerDAL,以便无人能意识到它的存在。

谢谢
编辑:
更具体地说:

using DAL; // it can be written
using DAL.IDAL; // it can be written
using DAL.DALFactory; // it can be written
using DAL.SQLServerDAL; // it dont want to allow anyone write that

不确定这是否是最佳解决方案,但:-

将SQLServerDAL类更改为internal。然后在properties/assemblyinfo.cs文件中,为需要访问SQLServerDAL的所有DLL添加:

using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Fully.Qualified.AssemblyName")]

这显然不能防止散播,但它不会被任何使用您的dll的人公开看到。

您所说的这些“子dll”是什么

我有一个类库项目

从这里,我假设您有一个DLL。在这种情况下,没有所谓的“子DLL”。在项目的子文件夹中定义的类是单个DLL的一部分。它们位于子文件夹中这一事实没有任何区别。如果已将子文件夹名称添加到每个类的命名空间中,则所有这一切都意味着生成类型的名称将包括其中的文件夹名称


如果要使某些类型成为内部类型,请使用关键字。不幸的是,没有办法使给定子文件夹下的所有类都成为内部类。如果要这样做,您需要将
internal
关键字添加到子文件夹中的每个类定义中。

如注释中所述,您可以添加要在父项目中作为资源文件隐藏的DLL。因此,您必须添加已编译的DLL,并在解决方案中将其标记为“嵌入式资源”

第二步是在父库中加载DLL以访问它

Stream stream = GetType().Assembly
               .GetManifestResourceStream("<<FULL QUALIFIED DLL NAME>>");
if (stream == null)
    throw new InvalidDataException("<<FULL QUALIFIED DLL NAME>> not found.");

byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int) stream.Length);

Assembly assembly = Assembly.Load(buffer);
Stream=GetType().Assembly
.GetManifestResourceStream(“”);
if(流==null)
抛出新的InvalidDataException(“未找到”);
byte[]buffer=新字节[stream.Length];
读取(缓冲区,0,(int)stream.Length);
组装=组装。加载(缓冲);
获得程序集引用后,可以着手获取要访问的类和方法

var sqlServerDAL = assembly.GetType("<<FULL QUALIFIED CLASS NAME>>");
var method = sqlServerDAL.GetMethod("<<METHOUD>>", BindingFlags.Public);
var sqlServerDAL=assembly.GetType(“”);
var method=sqlServerDAL.GetMethod(“”,BindingFlags.Public);

我知道这是一种非常令人讨厌的混淆某些类的方法,但它是有效的。因为DLL不在目录中,您也不能简单地键入名称空间来访问类。

这对于名称空间是不可能的,因为它们在元数据级别上不存在。按照其他人的建议,将名称空间SQLServerDAL中的所有类都设置为内部类,或者将SQLServerDAL设置为静态内部类而不是名称空间。在这种方法中,SQLServerDAL内部的类将成为嵌套类,并且从DAL程序集外部无法访问:

// what you have now:
namespace DAL.SQLServerDal
{
    public class A {}
    public class B {}
}

// in other assembly
using DAL.SQLServerDal ; // ok
new A () ; // ok

// with internal classes:
namespace DAL.SQLServerDal
{
    internal class A {}
    internal class B {}
}

// in other assembly
using DAL.SQLServerDal ; // ok
new A () ;               // error: A is inaccessible due to protection level

// what I propose:
namespace DAL
{
    internal static class SQLServerDal
    {
        public class A {}
        public class B {}
    }
}

// in other assembly
using DAL.SQLServerDal ; // error: namespace DAL.SQLServerDal does not exist

但是,如果使用反射或代码生成,如果所使用的库不正确支持嵌套类,则可能会出现问题。

为什么?那有什么用呢?如果您只是不分发该实现,其他人就不会知道它的存在。如果您这样做,反射可以很容易地找到它(或者像resharper这样的工具)。您正在寻找内部说明符,特别是用于限制对程序集内部的访问的说明符吗?除非我误解了你的问题,否则请告诉我。内部说明符仅隐藏标记为内部的类。但是用户仍然可以看到SQLServerDAL名称空间。我只是想知道这是否可能。如果SQLServerDAL文件夹的所有内容都标记为内部,那么名称空间也不会公开可见。@MarcArmstrong我尝试过,但没有任何效果。我在SQLServerDAL中将每个类都更改为internal,但SQLServerDAL仍然可见。是的,我指的是子文件夹,没有子DLL。不过,您知道它可以像dll一样与using语句一起使用。例如,使用DAL.SQLServerDAL;在这一点上,我不希望任何人都可以使用list将其放入。好的-因此,在这种情况下,将类设置为内部-请参阅我的answerSQLServerDAL中的链接在其他库中仍然可见。那么您还没有设置它internal@AdamRalph我把所有的课程都改为内部课程。例如,假设有一个名为SQLServerDAL的子文件夹。在这个文件夹中,我有一个客户类。我只能让客户成为内部客户,所以我做到了。程序员不能看到客户类,因为它是内部的。到现在为止还可以。但是程序员仍然可以使用DAL.SQLServerDAL添加数据;语句,但在其中找不到任何公共类。我只是不想让他们看到DAL库中有一个名为SQLServerDAL的子文件夹。不幸的是,恕我直言,这是不可能的。任何人都可以使用Reflector或ildasm查看您的所有代码和元数据。唯一真正的补救办法就是混淆你的代码。我已经将所有类标记为内部类。但情况不是阶级,而是阿萨德。SQLServerDAL是DAL库中的一个子文件夹。尽管所有类都在SQLServerDAL文件夹(DAL.SQLServerDAL名称空间)中,但人们仍然可以在使用列表中引用DAL.SQLServerDAL名称空间。我试图对@AdamRalphok;)的评论做出解释我在另一个项目中使用了一个解决方案。但我手头没有密码。主要思想是将DLL放入第一个DLL的资源中,并从嵌入的资源中加载它。如果你在那之前找不到解决方案,我会在晚上把代码发给你。是的,我想看看你的解决方案。这可能会有帮助,我们也可以在这里分享和讨论。谢谢你的编辑,展示了你这样做的方式。正如你提到的,这真是一种令人讨厌的方式。所以我想我会让它可见。我