4

インターフェースの使い方が間違っている気がします。インターフェイスは、具象クラスが順守しなければならないコントラクトであることを私は知っています。

だから私は私が解決しようとしている問題を説明します、そして多分誰かが私を正しい方向に向けることができます。

リクエストに対してページを返すアプリを作成しています。Cms、Product、Categoryの3つのページタイプがあります。

3つすべてで、次のインターフェイスを実装する必要があります。

public interface IPage
    {
        PageType PageType { get; set; }
        PageContent Content { get; set; }
        Meta Meta { get; set; }
    }

これらのプロパティは、ページタイプに関係なく再クエリされます。

ページには、タイプに応じて追加のプロパティがある場合があります。たとえば、カテゴリページは次のようになります。

public class CategoryPage : IPage
    {
        public PageType PageType { get; set; }
        public PageContent Content { get; set; }
        public Meta Meta { get; set; }

        public List<Product> Products { get; set; }
    }

現在、要求されたURLのページを返すページサービスがあります。

PageTypeに基づいて、返されるページのタイプを認識します。

問題は、pageServiceがIPageを返すため、任意のページタイプを返すことができることです。

これは、すべてのコンクリートがインターフェイスを実装しているわけではないため、問題です。カテゴリページの場合は、リストもあります。これは、コンクリートタイプにキャストしない限り、アクセスできません。

しかし、ジェネリックページタイプを返し、受信者にそれが具体的であるかを知らせる方法はありますか?

その瞬間が最善の方法ではないということを私がどのように行っているかを確信しており、この小さな問題をどのように解決できるかについて、いくつかの方向性とアドバイスを求めています。

ありがとう

アップデート

私はキャストに落ち着きました。

いくつかのクラスがいくつかの基本プロパティを使用するだけでなく、独自のプロパティを実装する状況を処理するためのより良い方法があるはずです。サービスからこれらのクラスの1つを取得するときは、関連するプロパティを操作できるように、何を取得したかを知る必要があります。

あるいは、私がここでやろうとしていることはまったく間違っているので、別のアプローチを取る必要があるかもしれません。今のところは頑張っていきたいと思いますが、考え続けます。

アップデート2

これを行う方法を変更したので、キャストは必要ありません。操作中のページのタイプを識別するために使用するPageType列挙型があります。

これは、必要なすべてを継承するIpageと相まって、十分に優れたソリューションのようであり、キャストの必要性を排除します。

4

4 に答える 4

2

isキーワードを使用すると、参照しているオブジェクトが特定のタイプであるかどうかをいつでも確認できます。

if(obj is Class1) {

とはいえ、デザインで具体的なタイプを知る必要がある場合は、デザイン自体に問題がある可能性があります。クラス間で動作に違いがある場合は、クラスの外部に実装するためにキャストするのではなく、クラスの内部に違いを実装します。

于 2012-01-28T16:55:31.827 に答える
1

受信者が具体的なタイプを認識している必要がある場合は、インターフェイスを適切に使用していません。

ページを返す場合、それがどのようなページであるかを知る理由は実際にはありません。Renderインターフェイスにメソッドを追加しIPageて、受信者が行う必要があるのは呼び出しだけRender()で、残りはページが処理するようにします。

于 2012-01-28T16:52:29.460 に答える
0

サービスから返されるインターフェースが具象型であることを確認する2つの方法があります。

        IPage page;
        if (page is CategoryPage)
        {
           // use type here
        }

        CategoryPage categoryPage = page as CategoryPage;
        if (categoryPage != null)
        {
          // use type here
        }
于 2012-01-28T16:59:34.897 に答える
0

理想的には、特にジェネリックスが存在することを考えると、タイプキャストを使用する必要はほとんどありません。ただし、実用的な観点からは、タイプキャストを回避するために膨大な長さを使用するよりも、タイプキャストを使用する方がよい場合があります。

ある意味では、あるオブジェクトには存在するが他のオブジェクトには存在しない能力を使用する必要がある場合に、異なる能力を持つオブジェクトのコレクション(または異なる能力を返すファクトリメソッド)を持つことはエレガントではありません。確かに次のようなことを言うことは可能です

  IInterfaceThatMayOrMayNotBePresent foo = bar as IInterfaceThatMayOrmayNotBePresent;
  if(foo!= null)
    foo.MethodOfThatInterface();

しかし、それは少しコードの臭いです。多くの場合、リスト内のすべてのインスタンスに存在しないメソッドを使用する必要がある理由を判断し、より優れたクラス設計が役立つかどうかを判断することをお勧めします。

たとえば、「Wowzo」が発生した場合に通知を受け取りたいオブジェクトの種類があるとします。他のタイプは気にしません。さらに、両方のタイプのオブジェクトを含むリストがあると予想され、気になるすべてのアイテムに通知する必要があります。上記の型チェックパターンを使用して、それを必要とするアイテムのみに通知することもできますが、より効率的なアプローチがあります。2つのインターフェイスを定義できます。後者は最初のインターフェイスを継承しますIAcceptWowzoNotificationsIActOnWowzoNotifications最初のクラスを実装するが2番目のクラスは実装しないクラスは、空のメソッドを使用してWowzo通知を実装することが期待されます。リスト内のすべてのアイテムがIAcceptWowzoNotificationsを実装している場合、そのような通知で何かを行うかどうかに関係なく、通知が必要なアイテムを確認するよりも、リストの全員に通知する方が高速です。

このアプローチは完全にコストがかからないわけではないことに注意してください。まず、デフォルトのメソッド実装を提供するインターフェイスが用意されていないため、実装するすべてのタイプでIAcceptWowzoNotificationsスタブメソッドを定義する必要があります。さらに、アイテムがリストに追加される唯一の理由がWowzo通知を送信することであり、リストにアイテムを追加するよりもリストの全員への通知が頻繁に発生する場合は、次のことを確認することをお勧めします。アイテムは、リストに追加する前に実装されIActOnWowzoNotificationsます。リストにアイテムを追加するのではなく、リストに追加する必要がある場合とない場合があります。

インターフェイスの継承階層は非常に強力で、多くの場合、十分に活用されていません。インターフェイスの実装では、どのメンバーがどの祖先インターフェイスからのものであるかを気にする必要がないため、クラスの分割よりもはるかに少ない頭痛でインターフェイスを簡単に分割できます。

于 2012-01-28T18:02:30.933 に答える