简体   繁体   English

C#中的内部属性设置器

[英]Internal property setters in C#

I'm trying to figure out a good way to approach this. 我正在试图找到一个很好的方法来解决这个问题。 I have a Customer class which implements the ICustomer interface. 我有一个Customer类,它实现了ICustomer接口。 This interface has a number of properties in it: 该界面中包含许多属性:

public interface ICustomer
{

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

I only want certain classes to have the ability to set those properties however; 我只希望某些类能够设置这些属性; namely, those classes in the project. 即项目中的那些课程。 So I thought about making the setter internal : 所以我想到让setter internal

public class Customer : ICustomer
{

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

I'd like to mark that setter as internal in the interface however, so there's no chance someone implements ICustomer and someone outside the assembly modifies those properties. 我想将该setter标记为接口内部,因此不可能有人实现ICustomer,并且程序集之外的人修改这些属性。 Is there a good way to do this? 有没有办法做到这一点?

The properties in the interface should be read only. 界面中的属性应该是只读的。 It's acceptable for the concrete class that implements the interface to have a setter even if none is defined in the interface. 即使接口中没有定义set接口,实现接口的具体类也可以接受。

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; }
}

If it's really important that the setter be exposed through an interface, rather than having the interface being entirely read-only, you can use something like this: 如果通过接口公开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; }
    }
}

I'd like to mark that setter as internal in the interface however, so there's no chance someone implements ICustomer and someone outside the assembly modifies those properties. 我想将该setter标记为接口内部,因此不可能有人实现ICustomer,并且程序集之外的人修改这些属性。 Is there a good way to do this? 有没有办法做到这一点?

No. Property members are always public, unfortunately. 不幸的是,不幸的是,物业成员总是公开的。 Additionally, messing around with access levels on properties where part of it is specified on the interface gets painful, IIRC. 此外,在界面上指定部分属性的访问级别搞乱,IIRC。 What you can do is this: 可以做的是这样的:

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

Then from the outside it'll look like Customer only implements ICustomer , but from inside your code will see that it implements ICustomerWithSetMethods . 然后,从外面看,它会像Customer只实现ICustomer ,但是从你的代码会看到,它实现ICustomerWithSetMethods

Unfortunately that doesn't play nicely if your API needs to declare any public methods where you'd really like to just declare a return type of ICustomer , but you'll actually know that it's always ICustomerWithSetMethods . 不幸的是,如果你的API需要声明任何公共方法,而你真的只想声明一个返回类型的ICustomer ,那么ICustomer不能很好地发挥ICustomer ,但实际上你知道它总是ICustomerWithSetMethods

Assuming you still want to allow multiple implementations, you could potentially go for an abstract class instead: 假设您仍然希望允许多个实现,您可能会改为使用抽象类:

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);
}

Now we have the slight oddity that no-one outside the assembly can extend your CustomerBase , because there are abstract methods they'd have to override that they can't even see - but it does mean you can use CustomerBase everywhere in your API. 现在我们有一点点奇怪的是,程序集之外的任何人都无法扩展你的CustomerBase ,因为有些抽象的方法他们不得不覆盖甚至看不到 - 但它确实意味着你可以在你的API中的任何地方使用CustomerBase

This is the approach we took in Noda Time for calendar systems in the end - I blogged about it when I first came up with the plan. 这是我们最终在Noda Time中为日历系统采用的方法 - 当我第一次提出计划时,我在博客上写了这篇文章。 I generally prefer interfaces to abstract classes, but the benefit here was significant. 通常更喜欢接口来抽象类,但这里的好处是显着的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM