2012-01-20 28 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); 
    } 

并实现派生类相应

相关问题