我正试图想出一个很好的方法来解决这个问题。我有一个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,并且程序集之外的人修改这些属性。有没有办法做到这一点?
答案 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。我通常更喜欢抽象类的接口,但这里的好处是显着的。