0

我有一个我正在定义的公共类,它最终将成为 API 的一部分,因此它必须具有某些公共属性。但是,我还希望某些属性是只读的,除非它们是在我自己的项目中创建的(例如,如果用户拥有我们的 API,他们可以创建一个 User 对象,但他们不能写入其 ID字段,只有当我们从数据库中提取它时才会填写)。

我的想法是让两个单独的程序集使用相同的命名空间,即“公共”DLL 和“私有”DLL。公共 DLL 中的原型将如下所示:

namespace CompanyName
{
  public partial class User
  {
    public Id { get; }
    public Name { get; set; }
  }
}

并且私有 DLL 将具有以下内容:

namespace CompanyName
{
  public partial class User
  {
    public Id { set; }
  }
}

这行得通吗?如果没有,有什么更好的方法来做到这一点?

4

5 回答 5

9

部分类不能跨越程序集,因此这不起作用。

您可以将您的班级定义为:

namespace CompanyName
{
    public class User
    {
        public Id {get;internal set;}
        public Name {get;set;}
    }
}

这意味着只有对您的类具有内部访问权限的代码才能设置Id属性的值。如果您需要从程序集外部设置它,请确保您的程序集是强名称的,然后您可以使用InternalsVisibleTo属性将您的程序集的内部访问权限授予您的另一个程序集(设置值的那个Id)。


我最近不得不为我正在处理的 API 做一些与此非常相似的事情。我们的 API 主要是使用接口定义的,所以我能够通过一个作为公共部分的公共 API 项目和一个内部 API 项目来实现这一点,该项目形成我们内部代码使用的 API,内部接口源自公共接口. API 接口的实现实现了这两个接口,这意味着我们的内部代码可以访问 API 中不公开的部分。

于 2009-12-11T23:06:06.473 回答
5

不,这行不通。部分类在编译时合并:您​​不能将成员添加到已编译的类中。

根据您的代码的确切布局方式,更好的方法是提供内部设置器:

public int Id { get; internal set; }

如果您需要能够从另一个程序集进行设置,但只能控制一个程序集,则可以使用 InternalsVisibleToAttribute 授予该程序集对内部设置器的访问权限。

于 2009-12-11T23:08:00.463 回答
2

我怀疑这会奏效。我想部分类被一起编译到同一个程序集中,而不是由 CLR 处理。您可能想查看internal关键字。

也许做这样的事情

abstract internal class UserPrototype
{
    protected Property....
}


sealed class User : UserPrototype
{
    public ...
}
于 2009-12-11T23:07:17.053 回答
0

即使您可以这样做,您的私有属性和字段仍然可以通过反射发现。从GetProperty 的 MSDN 页面

以下BindingFlags过滤器标志可用于定义要包含在搜索中的属性:

您必须指定BindingFlags.InstanceBindingFlags.Static才能获得回报。

指定BindingFlags.Public以在搜索中包含公共属性。

指定BindingFlags.NonPublic以在搜索中包含非公共属性(即私有和受保护的属性)。

于 2009-12-11T23:13:26.747 回答
0

设计 API 的诀窍是考虑接口的类别(在这种情况下是抽象类)。请看一下这段代码:

public abstract class User
{
    protected String _name;
}

public sealed class PublicUser : User
{
    public String Name
    {
        get{ return this._name; }
    }
}

public class PrivateUser : User
{
    public String Name
    {
        get { return this._name; }
        set { this._name = value; }
    }
}

显然,您可以使用任何类/命名空间名称,这只是为了让事情变得清晰。如您所见,所有类都是公共的,因此现在由您决定哪个 DLL 可用于您的客户端。

于 2009-12-12T00:31:03.430 回答