C#中的内部属性设置器

时间:2012-11-28 20:54:07

标签: c# properties setter internal

我正试图想出一个很好的方法来解决这个问题。我有一个Customer类,它实现了ICustomer接口。该界面中包含许多属性:

public interface ICustomer
{

   string FirstName {get; set;}
   string LastName  {get; set;}
}

我只希望某些类能够设置这些属性;即项目中的那些课程。所以我考虑制作setter internal

public class Customer : ICustomer
{

   string FirstName {get; internal set;}
   string LastName  {get; internal set;}
}

我想在接口中将该setter标记为内部,因此不可能有人实现ICustomer,并且程序集之外的人修改这些属性。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:17)

界面中的属性应该是只读的。即使接口中没有定义设置器,实现接口的具体类也是可以接受的。

public interface ICustomer
{
   string FirstName { get; }
   string LastName  { get; }
}

public class Customer : ICustomer
{
   public string FirstName { get; internal set; }
   public string LastName  { get; internal set; }
}

如果通过接口公开setter非常重要,而不是让接口完全是只读的,你可以使用这样的东西:

public interface IReadCustomer
{
    string FirstName { get; }
    string LastName { get; }
}

internal interface IWriteCustomer
{
    string FirstName { set; }
    string LastName { set; }
}

internal interface IReadWriteCustomer : IReadCustomer, IWriteCustomer
{ }

public class Customer : IReadWriteCustomer
{
    private string _firstName;
    private string _lastName;

    public string FirstName
    {
        get { return _firstName; }
        internal set { _firstName = value; }
    }
    public string LastName
    {
        get { return _lastName; }
        internal set { _lastName = value; }
    }

    string IReadCustomer.FirstName
    {
        get { return FirstName; }
    }

    string IReadCustomer.LastName
    {
        get { return LastName; }
    }

    string IWriteCustomer.FirstName
    {
        set { FirstName = value; }
    }

    string IWriteCustomer.LastName
    {
        set { LastName = value; }
    }
}

答案 1 :(得分:6)

  

我想在接口中将该setter标记为内部,因此不可能有人实现ICustomer,并且程序集之外的人修改这些属性。有没有办法做到这一点?

没有。不幸的是,物业成员总是公开。此外,在界面上指定部分属性的访问级别搞乱,IIRC。您可以做的是:

public interface ICustomer
{
    string FirstName { get; }
    string SecondName { get; }
}

internal interface ICustomerWithSetMethods : ICustomer
{
    void SetFirstName(string name);
    void SetLastName(string name);
}

public class Customer : ICustomerWithSetMethods

然后从外部看起来Customer只会实现ICustomer,但是从里面你的代码会看到它实现{ {1}}。

不幸的是,如果你的API需要声明任何公共方法,而你真的只是声明一个返回类型ICustomerWithSetMethods,那么它就不能很好地发挥作用,但实际上你会知道它总是ICustomer

假设你仍然想要允许多个实现,你可能会改为抽象类:

ICustomerWithSetMethods

现在我们有一点点奇怪的是,程序集之外的任何人都无法扩展你的public abstract class CustomerBase { public abstract string FirstName { get; } public abstract string LastName { get; } internal abstract void SetFirstName(string name); internal abstract void SetLastName(string name); } ,因为他们必须覆盖的抽象方法甚至不能看到 - 但这确实意味着您可以在API中的任何地方使用CustomerBase

这是我们最终在Noda Time中为日历系统采用的方法 - 当我第一次提出计划时我blogged about it。我通常更喜欢抽象类的接口,但这里的好处是显着的。