2012-01-20 63 views
2

我有一個基類叫Base如何在基類中有更通用的方法時重寫基類中的方法?

protected virtual string GetFormattedAttribute(string propertyName, object propertyValue) 

propertyValue的定義爲::

dynamic propertyValue 

所以不同類型的值被分配給它和適當的方法被自動調用作爲該基類定義的方法。例如,我有DateTime如在相同的基類的另一虛擬方法:

protected virtual string GetFormattedAttribute(string propertyName, DateTime propertyValue) 

這工作完全。現在,我有一個dervied類中,我定義了同樣的方法,它接受一個List<Contact>

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

然而,這不會被調用,並與propertyValue第一種方法爲Baseobject就被調用(I」 m用派生類對象調用此方法)。我在派生類方法中嘗試了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) 

如果所有類型有某種共同的通用格式這將是有益的。

初次檢查看起來不錯,但如果你的類型沒有一些通用的格式化模式(我認爲是這種情況)會怎麼樣。我不是在一個類中實現所有的格式化,而是更願意去實現和征服,實現一些與他們正在格式化的類型緊密相關的小型專用格式化類。這樣的類將實現通用接口IPropertyFormatter<T>

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

,將需要實現這個接口中最通用類只是當你爲Object.ToString()做的就是價值,因此,我們有ObjectPropertyFormatter爲最通用的實現IPropertyFormatter

public class ObjectPropertyFormatter : IPropertyFormatter<Object> 
    { 
     public string FormatValue(Object value) 
     { 
      //object fallback formatting logic 
      return value.ToString(); 
     } 
    } 

現在假設某些類型需要特殊處理。然後我們繼續爲它們實現特定的屬性格式化器。因此,您不必爲所有特定情況擁有一個具有大量重載的類,而是擁有處理格式邏輯的專用類。在這個例子中有一個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"; 
     } 
    } 

你可以有更多的類,如List等,每個都有自己的格式邏輯與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)); 
    } 

如果您格式化邏輯也依賴於propertyName的那麼所有你需要做的是界面修改到:

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

並實現派生類相應

相關問題