1

データを提供する API に変更を加えています (これは元の質問の更新です)。一部の検索では、作成者に関するデータが必要で、IAuthorオブジェクトが取得されます。API には、インターフェースと、と呼ばれるIAuthorを実装する単一の具象クラスがあります。IAuthorAuthor

著者が小説家としてフラグ付けされている場合、メソッドの動作を変更Search.GetBooksByAuthorして別のセマンティックを与える必要があります。オープン/クローズの原則について聞いたことがありますが、 IAuthorand/or Authorand/orクラスを変更するとSearchこれに違反するようです (ただし、Bookクラスは間違いなく変更されていません)。では、この単純な変更を行うにはどうすればよいでしょうか。

たとえば、私はもともと次のようなことを考えていましたが、Searchクラスを変更する必要があるため、私の考えはおそらく不安定です。

//Before
class Search 
{
   public Books[] GetBooks(IAuthor author){
       // Call data access GetBooks...
    }
}


//After
class Search
{
   public Books[] GetBooks(IAuthor author){
       // To maintain pre-existing behaviour
       // call data access GetBooks method with SQL param @AsNovelist = false...
       // (or don't pass anything because the SQL param defaults to false)
    }

   public Books[] GetBooksAsNovelist(IAuthor author){
       // To get new behaviour
       // call data access GetBooks method with SQL param @AsNovelist = true
       // so that their non-fiction books are omitted from results
    }
}
4

6 に答える 6

1

著者がであるかどうかを知るために何かを変更する必要があることは明らかなように思われるかもしれませNovelistん。これは2つの方法のいずれかで行うことができます。理論的には何も変更する必要はありませんが、新しいクラスが必要です。

public class Novelist : Author, IAuthor { }

次に、小説家をあなたの方法に渡し、次にあなたのタイプの著者を決定することができます。

class Search 
{
   public Books[] GetBooks(IAuthor author){
       if(author is Novelist)
         //Do some stuff or set a flag/bool value
    }
}

または、前述のように、作成者インターフェイスにブール値のメンバーを実装し、それを確認します。ただし、上記の場合、クラス構造を変更できなくなります。

これは、あなたの小説家が実際にはまだ作家であり、それ自身のタイプを持っていることを意味します。メソッドのシグネチャは同じままで、クラス構造は同じままです。「異なるタイプの作成者」のタイプがあるだけです。これは理論的には問題ありません。テストするには、以下のように呼び出します。

GetBooks(new Novelist());
于 2013-01-17T09:16:42.953 に答える
1

C#言語の拡張機能を使用できます。

http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspxを参照してください

拡張機能を使用すると、クラスをそのまま維持することで、クラスに機能を追加できます。

あなたの場合、あなたは次のように書くことができます:

public static class SearchExtensions
    {
        public static Books[] GetBooks(this Search search, IAuthor author)
        {
            //new logic
        }
    }   

Searchオブジェクトからこの新しいメソッドにアクセスでき、Searchクラスもそのまま残ります。

これがお役に立てば幸いです。

于 2013-01-17T09:20:25.397 に答える
1

拡張、継承、または制御の反転なしで機能を追加できるように、クラスを部分的にすることができます。

// file: Search.cs

partial class Search
{
    public Books[] GetBooks(IAuthor author) { ... }
}

// file: Search.Advanced.cs

partial class Search
{
    public Books[] GetBooksAsNovelist(IAuthor author) { ... }
}

結果:

http://i.snag.gy/VowNv.jpg

于 2013-01-17T10:04:09.170 に答える
1

クラスを拡張するために、C# .NETは .NET 3.5 で拡張メソッドを導入しました。その主な目的は、既存のコードを変更せずにクラスを拡張することです。

public static class SearchExtensions
{
  public static Books[] GetBooksAsNovelist(this Search search, IAuthor author)
  {
     // Perform novelist search
  }
}

その後、次のように通常どおり Search クラスを呼び出すことができます。

Search.GetBooksAsNovelist(author);
于 2013-01-17T09:19:26.567 に答える
1

フィルタリングに述語を使用するのはどうでしょうか。

class Search
{
   public Books[] GetBooks(IAuthor author, Func<IAuthor, bool> filter){
       // ...
    }
}

search.GetBooks(author, a => a.IsNovelist)
于 2013-01-17T09:12:42.727 に答える
0

検索クラスのメソッドを仮想のままにしておくと、誰でもオーバーライドして新しい動作を作成できますか?

于 2013-01-17T09:13:59.157 に答える