C# C语言中的内部属性设置程序#

C# C语言中的内部属性设置程序#,c#,properties,setter,internal,C#,Properties,Setter,Internal,我正在想办法解决这个问题。我有一个实现ICCustomer接口的Customer类。此接口中有许多属性: public interface ICustomer { string FirstName {get; set;} string LastName {get; set;} } 但是,我只希望某些类能够设置这些属性;即,项目中的那些类。因此,我考虑将setter设置为内部: public class Customer : ICustomer { string Firs

我正在想办法解决这个问题。我有一个实现ICCustomer接口的Customer类。此接口中有许多属性:

public interface ICustomer
{

   string FirstName {get; set;}
   string LastName  {get; set;}
}
但是,我只希望某些类能够设置这些属性;即,项目中的那些类。因此,我考虑将setter
设置为内部

public class Customer : ICustomer
{

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

但是,我想在接口中将该setter标记为内部,这样就不可能有人实现ICCustomer,也不可能有人在程序集外部修改这些属性。有什么好办法吗

接口中的属性应为只读。即使接口中没有定义setter,实现接口的具体类也可以使用setter

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; }
    }
}
但是,我想在接口中将该setter标记为内部,这样就不可能有人实现ICCustomer,也不可能有人在程序集外部修改这些属性。有什么好办法吗

不。不幸的是,酒店会员总是公开的。此外,在接口上指定部分属性的属性上混淆访问级别会让人痛苦,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
只实现了
iccustomer
,但从代码内部看,它实现了
iccustomerwithsetmethods

不幸的是,如果您的API需要声明任何公共方法,而您真的只想声明返回类型为
ICCustomer
,但实际上您会知道它总是
ICCustomerWithSetMethods
,那么这并不能很好地发挥作用

假设您仍然希望允许多个实现,那么您可以选择一个抽象类:

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);
}
现在我们有一点奇怪,程序集之外没有人可以扩展您的
CustomerBase
,因为有一些抽象方法他们必须重写,他们甚至看不到-但这确实意味着您可以在API中的任何地方使用
CustomerBase


这是我们在最后采用的日历系统的方法——我第一次提出计划的时候。与抽象类相比,我通常更喜欢接口,但这里的好处非常显著。

谢谢您的帮助。但是,如果我这样做,并且消费类使用ICCustomer,它就无法访问setter。@larryq这就是关键所在,因为接口没有提交给setter。如果您想要实现第二个内部接口来添加setter,您可以。我经常有一系列接口:这是一个真实的例子:
IDimensionedMap
只提交二维实体的维度
IReadMap
具有可读属性,对于只读或计算映射,
IReadMap:IDimensionedMap
然后是
IWriteMap:IReadMap
。但这是一个复杂的可扩展实用程序类家族。(如果您好奇的话,这些是2d Hilbert空间,不是字典。)@larryq虽然我不确定您是否需要它,但我添加了一个替代实现,其中接口定义了一个内部集合方法。谢谢先生们,这些都是很好的提示,非常感谢。你错过了FirstName和FirstName的类型和范围SecondName@JonSkeet我同意您的方法,但是当随着时间的推移,可维护性将成为一个问题时,我通常同时实现接口和抽象基类。这需要额外的键入,但是像Resharper这样的工具使它更容易,这意味着当您有一个复杂的对象族时,您可以有多个抽象实现,也许一个会扩展到你自己的代码库之外。@SAJ14SAJ:这不是一个额外键入的问题——我很希望能够在上面加一个接口;问题是您不能在接口中声明内部成员。这就是这个问题的重点。(在野田佳彦的例子中,我真的不介意第三方不能添加新的实现。我们故意隐藏了许多必须是抽象成员签名的类型。)@JonSkeet抱歉,我错过了这个微妙之处。我认为有第二个内部接口扩展了第一个公共接口,这是合法的。一般来说,C#比任何其他经典对象语言更接近于表达我在该范例中想要的东西!我对这些情况的妥协也见于一些CLR库类——为接口的不受支持部分抛出一个IllegalOperationException,提供允许您首先测试的属性,并记录其中的bleep。@SAJ14SAJ:不幸的是,当您需要引用成员签名中的内部类型时,这没有帮助。。。我似乎比其他人更喜欢这样的极端情况!