2012-01-20 11 views
2

私はBaseという基本クラスを持っています。 propertyValueのように定義される基本クラスでより一般的なメソッドがある場合、基本クラスのメソッドをオーバーライドする方法は?

protected virtual string GetFormattedAttribute(string propertyName, object propertyValue) 

:この基本クラスは、として定義されたメソッドを有する

dynamic propertyValue 

値のように、異なるタイプは、それに割り当てられ、適切な方法は、自動的に呼び出されます。これは完璧に動作

protected virtual string GetFormattedAttribute(string propertyName, DateTime propertyValue) 

:たとえば、私はDateTimeように同じ基底クラス内の別の仮想メソッドを持っています。今、私はList<Contact>を受け入れるのと同じ方法、定義したderviedクラスています

protected string GetFormattedAttribute(string propertyName, List<Contact> contacts) 

これは、しかし、呼び出されることはありませんし、BaseobjectとしてpropertyValueとの第1の方法は「I(代わりに呼び出されますこのメソッドを派生クラスオブジェクトで呼び出す)。派生クラスのメソッドでnewoverrideというキーワードを試しましたが、うまくいきません。どのように私はこの結果を達成することができます任意のアイデア?

+0

応じ子孫クラスを実装するには、あなたはとしてそれを宣言することができますジェネリック? – abatishchev

+0

いいえ、それはオプションではありません – wasimbhalli

+0

あなたはメソッドを使用しているコードを表示できますか?あなたの試みを見ておくと便利です。 –

答えて

3

これはオーバーライドとは関係ありません。 オーバーロードGetFormattedAttributeに作成しています。 Base型の変数にGetFormattedAttributeを呼び出すと、インスタンスが実際に派生型であっても、派生クラスのオーバーロードについてはわかりません。

簡単に言えば、派生クラスのオーバーロードは、派生クラスの変数またはそれから派生するクラスに対して呼び出されている場合のみ呼び出されます。このメソッドは保護されているので、GetFormattedAttributeを基底クラスのどこかに呼び出すと仮定します。このシナリオでは、オーバーロードされたGetFormattedAttributeを派生クラスで使用することはできません。

  1. オーバーライド派生クラスでobjectパラメータを持つバージョン
  2. は、そのオーバーライドされたバージョンに型チェックを入れて:あなたが探している結果を達成するために

    一つの方法は、このようなものになるだろう。タイプは、過負荷List<Contact>呼び出し、そうでない場合は基本実装を呼び出す

であれば、このような何か:

class Derived : Base 
{ 
    protected override string GetFormattedAttribute(string propertyName, 
                object propertyValue) 
    { 
     var list = propertyValue as List<Contact>; 
     if(list == null) 
      return base.GetFormattedAttribute(propertyName, propertyValue); 
     else 
      return GetFormattedAttribute(propertyName, list); 
    } 

    protected string GetFormattedAttribute(string propertyName, 
              List<Contact> contacts) 
    { 
     // ... 
    } 
} 
+0

だから、ベースでは、どのように派生クラスのメソッドを呼び出すことができますか? – wasimbhalli

+0

私はすでにそれをしました...ありがとう! – wasimbhalli

+0

@wasimbhalli:更新を参照してください。他の方法はありません。基本クラスは、それから派生したクラスを知らない。 –

1

あなたが欲しいものを達成するためにジェネリックを使用することができることを私には思えます。

だから、ベースでは、すべてのタイプが共通の一般的なフォーマットのいくつかの並べ替えを持っている場合、これは有用であろう

protected virtual string GetFormattedAttribute<T>(string propertyName, T propertyValue) 

だろう。

最初の検査でうまくいくようですが、タイプに一般的な書式設定パターンがない場合はどうなりますか?すべての書式を1つのクラスに実装するのではなく、フォーマットしている型に密接に結びついた小さな専用の書式付きクラスを実装することをむしろ克服して克服することになります。このようなクラスはObject.ToString()が値を取得するためにあなたがしたときにこのインタフェースを実装する必要があります最も一般的なクラスは、単に、それゆえ我々はの最も一般的な実装としてObjectPropertyFormatterを持っているIPropertyFormatter<T>

public interface IPropertyFormatter<T> { 
     string FormatValue(T value); 
    } 

ジェネリックインターフェイスを実装しますIPropertyFormatter

ここで、特殊な処理が必要な種類があるとします。次に、特定のプロパティフォーマッタを実装します。したがって、すべての特定のケースで過負荷のクラスを1つ持つのではなく、書式設定ロジックを処理するクラスを用意しています。この例ではDateTimePropertyFormatterBooleanPropertyFormatterがあり、彼らはそのように実装されるだろう:

public class DateTimePropertyFormatter : IPropertyFormatter<DateTime> 
    { 
     public string FormatValue(DateTime value) 
     { 
      //DateTime customised formatting logic 
      return "<b>" + value.ToString("yyyyMMdd") + "</b>"; 
     } 
    } 

    public class BoolPropertyFormatter : IPropertyFormatter<bool> 
    { 
     public string FormatValue(bool value) 
     { 
      //bool customised formatting logic 
      if (value) 
       return "yeaaah"; 
      else 
       return "nope"; 
     } 
    } 

あなたはこのようなリストなど、より多くのクラスを持っている可能性があり、その上、自分のフォーマッティングロジックと、それぞれがsingle responsibility principle

でインラインを保ちます

フォーマッタがあるので、すべてのフォーマッタを実行するにはどうすればよいですか?これがFormatterResolverが出場する場所です。書式を登録することができます。

/// <summary> 
    /// Class responsible for getting the right format resolver for a given type 
    /// </summary> 
    public class FormatterResolver 
    { 
     private ObjectPropertyFormatter _objectPropertyFormatter; 

     private Dictionary<Type, object> _registeredFormatters; 

     public FormatterResolver() 
     { 
      _registeredFormatters = new Dictionary<Type, object>(); 
      _objectPropertyFormatter = new ObjectPropertyFormatter(); 
     } 

     public void RegisterFormatter<T>(IPropertyFormatter<T> formatter) 
     { 
      _registeredFormatters.Add(typeof(T), formatter); 
     } 

     public Func<string> GetFormatterFunc<T>(T value) 
     { 
      object formatter; 
      if (_registeredFormatters.TryGetValue(typeof(T), out formatter)) 
      { 
       return() => (formatter as IPropertyFormatter<T>).FormatValue(value); 
      } 
      else 
       return() => (_objectPropertyFormatter.FormatValue(value)); 

     } 
    } 

formatResolverのインスタンスを格納し、すべてのフォーマッタを登録する必要があります。

public FormatterResolver _formatResolver; 

    public void RegisterFormatResolvers() 
    { 
     _formatResolver = new FormatterResolver(); 
     _formatResolver.RegisterFormatter(new BoolPropertyFormatter()); 
     _formatResolver.RegisterFormatter(new DateTimePropertyFormatter()); 
     //...etc 

    } 

あなたの方法は、このようなものになりますので、

public string GetFormattedAttribute<T>(T propertyValue) 
    { 
     return _formatResolver.GetFormatterFunc(propertyValue)(); 
    } 

を、テストにそれを置くための時間は、このすべての作業をしますか?これは、上記のコードが期待どおりに機能することを示す迅速な健全性テストです。そして、あなたがする必要があるだろうすべてはとのインタフェースを改正ある

[TestMethod] 
    public void TestFormatResolvers() 
    { 
     RegisterFormatResolvers(); 

     Assert.AreEqual("yeaaah", GetFormattedAttribute(true)); 
     Assert.AreEqual("nope", GetFormattedAttribute(false)); 
     Assert.AreEqual("<b>20120120</b>", GetFormattedAttribute(new DateTime(2012, 01, 20))); 
     Assert.AreEqual("5", GetFormattedAttribute(5)); 
    } 

書式設定ロジックはまた、プロパティ名に依存している場合:

public interface IPropertyFormatter<T> { 
     string FormatValue(string propertyName, T value); 
    } 

関連する問題