16

私はこれにアプローチする良い方法を見つけようとしています。ICustomer インターフェイスを実装する Customer クラスがあります。このインターフェイスには、いくつかのプロパティがあります。

public interface ICustomer
{

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

ただし、特定のクラスにこれらのプロパティを設定する機能を持たせたいだけです。つまり、プロジェクト内のクラスです。だから私はセッターを作ることを考えましたinternal:

public class Customer : ICustomer
{

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

ただし、そのセッターをインターフェイスの内部としてマークしたいので、誰かが ICustomer を実装し、アセンブリの外部の誰かがそれらのプロパティを変更する可能性はありません。これを行う良い方法はありますか?

4

2 に答える 2

24

インターフェイスのプロパティは読み取り専用である必要があります。インターフェイスに何も定義されていない場合でも、インターフェイスを実装する具象クラスにセッターが含まれていてもかまいません。

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

インターフェイスを完全に読み取り専用にするのではなく、インターフェイスを介してセッターを公開することが非常に重要な場合は、次のようなものを使用できます。

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; }
    }
}
于 2012-11-28T20:58:07.063 に答える
7

ただし、そのセッターをインターフェイスの内部としてマークしたいので、誰かが 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からはimplementsのみのように見えますが、コードの内側ICustomerからはimplementsであることがわかります。ICustomerWithSetMethods

残念ながら、API で public メソッドを宣言する必要があり、戻り値の型を宣言したい場合はうまく機能しませんが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);
}

ここで、アセンブリの外の誰もあなたの を拡張できないという少し奇妙な点があります。これは、オーバーライドする必要があり、見るCustomerBaseことさえできない抽象メソッドがあるためです。しかし、これは、API のどこでも使用できることを意味します。CustomerBase

これが野田時間の暦体系の最終的なアプローチであり、最初に計画を思いついたときにブログに書きました。私は通常、抽象クラスよりもインターフェイスを好みますが、ここでの利点は大きかったです。

于 2012-11-28T20:59:15.300 に答える