2012-01-28 9 views
4

インタフェースの使用が間違っていると感じました。私はインターフェイスがコンクリートクラスが遵守しなければならない契約であることを知っています。インターフェイスを返すが、コンクリートにはインターフェイスにないプロパティがある可能性があります。キャストでそれらを取得できますか?

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

リクエストに応じてページを返すアプリケーションを作成しています.Cms、Product、Categoryという3つのページタイプがあります。これらのプロパティは、どのようなページ・タイプを再クエリしている

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

すべての3つは、次のインタフェースを実装する必要があります。私は要求されたURLのページを返しますページサービスを持っている現時点で

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

ページは、カテゴリページはそうのような可能性があり、たとえば、その種類に応じて、余分な性質を有することができます。

PageTypeに基づいて、どのページタイプを返すかを知っています。

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

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

しかし、私は一般的なページタイプを返すことができ、受信機にそれが具体的であることを知らせる方法はありますか?

私はこの瞬間が最善の方法ではなく、この小さな問題をどのように解決できるかについていくつかの方向性や助言をしたいと思います。

おかげ

更新

私は、キャストのために定住しています。

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

多分私はここでやろうとしています。別のアプローチをとる。私は今私が持っていることを続けていくつもりだと思っています。私はこれをやっている私は道を変えた2

アップデートので、私は、キャストを必要としない、私は私が働いているページの種類を識別するために使用するページタイプの列挙型を持っています。

これは、必要なものすべてを継承するIpageと組み合わせると、十分な解決策であると思われ、キャストの必要がなくなります。

答えて

2

参照先のオブジェクトがis keywordを使用する特定のタイプのものであるかどうかは、常に確認できます。

if(obj is Class1) { 

つまり、デザインに具体的なタイプが必要な場合は、デザイン自体に問題がある可能性があります。クラス間で動作に違いがある場合は、の内部にの違いを実装して、それらをキャストしてクラス外に実装する必要はありません。

+0

私はインターフェイスの一部ではないプロパティの値を取得するためにキャストします。私はif(page.GetType == typeof(CategoryPage))を使用することを検討していた - しかし、私は本当にしたくない、私はデザインが間違っていることに同意する、質問の情報に基づいて、設計? –

1

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

ページを返す場合、ページの種類を知る必要はありません。 メソッドをIPageインターフェイスに追加すると、すべての受信者がRender()を呼び出し、ページが残りの部分を処理する必要があります。

+0

「私のインターフェイスの使用が間違っていると感じています。」 - 私の最初の文はあなたのものに同意します:)したがって質問です。私はレンダリング()メソッドのアイデアが好きです、それはいくつかの考えを与えるでしょう。 –

0

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

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

     CategoryPage categoryPage = page as CategoryPage; 
     if (categoryPage != null) 
     { 
      // use type here 
     } 
+0

ありがとう、問題は私がこれを行う必要はありませんが、私が使用しているデザインが間違っているようだが、私はそれをよりうまく実装する方法がわからない。たぶん私は私の質問に言い直す必要があります。 –

+0

はい、ジャスティンの答えは、あなたがすべてのクラスをコントロールしている方が良いです。 – Maggie

0

理想的には、特にジェネリックの存在を考えれば、型キャストを使う必要はほとんどありません。しかし、実用的な見地からは、しばしば型キャストを使用する方が、それらを避けるために巨大な長さに行くよりも優れています。

ある意味では、あるオブジェクトには存在するが他のオブジェクトには存在しない能力を使用する必要がある場合には、異なる能力を持つオブジェクトの集合(または異なる能力を返すファクトリメソッド)を持つことは、 。

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

のようなものを言うことは間違いありませんが、コードの匂いです。なぜリスト内のすべてのインスタンスに存在しないメソッドを使用する必要があるのか​​を判断し、より優れたクラス設計が役立つかどうかを判断することは良いことです。

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

この手法は、まったくコストがかかりません。まず、デフォルトのメソッド実装を提供するためのインタフェースがないため、IAcceptWowzoNotificationsを実装するすべての型はスタブメソッドを定義する必要があります。さらに、アイテムがリストに載る唯一の理由がWowzo通知を送信することであれば、リスト上の全員の通知がリストにアイテムを追加するよりも頻繁に発生する場合は、アイテムはリストに追加する前にIActOnWowzoNotificationsを実装しています。リストに項目を追加する場合は、リストに追加する必要はありません。

インターフェイス継承階層は非常に強力で、多くの場合、十分に活用されていません。インターフェイス実装がどのメンバがどの祖先インターフェイスから来たのか心配する必要がないという事実は、分割クラスで発生するよりもはるかに少ない頭痛でインターフェイスを分割することを容易にします。

関連する問題