2012-04-02 5 views
1

Ich habe einige Probleme, wahrscheinlich Missverständnisse, über das Schlüsselwort new mit Eigenschaften in abgeleiteten Klassen. Der Großteil der Dokumentation behandelt new über abgeleitete Methoden. Zum Beispiel:Eigenschaft mit neuem Schlüsselwort zur Laufzeit leer, aber Basiseigenschaft ist korrekt

[DataContract] 
[KnownType(typeof(PostCategory))] 
public class BaseCategory : IEquatable<BaseCategory> 
{ 
//... 

    /// <summary> 
    /// Enables access to child categories (immediate ones). Filled in by data access provider. Not serializable. 
    /// </summary> 
    public SortedDictionary<string, BaseCategory> Children { get; set; } 
//... 
} 

[DataContract] 
[KnownType(typeof(BaseCategory))] 
public class PostCategory : BaseCategory 
{ 
//... 
    public new SortedDictionary<string, PostCategory> Children { get; set; } 
//... 
} 

Dann habe ich in meiner Daten-Repository-Implementierung eine generische Implementierung für alle Klassen, die von BaseCategory abgeleitet sind. Ich tue dies:

public class CachedXmlCategorizationProvider<T> : ICategorizationRepository<T> where T : BaseCategory, new() 
    { 
     private readonly ICacheProvider _cacheProvider = AppServices.Cache; 
     private readonly string _file = Path.Combine(XmlProvider.DataStorePhysicalPath, typeof (T).Name, "categorization.xml"); 
     private SortedDictionary<string, T> _dictionary; 

    //... 
     private SortedDictionary<string, T> LoadFromDatastore() 
     { 
      if (!DefaultsExist()) 
      { 
       return CreateDefaults(); 
      } 

      var dcs = new DataContractSerializer(typeof (SortedDictionary<string, T>)); 
      XmlDictionaryReader reader = 
       XmlDictionaryReader.CreateTextReader(new FileStream(_file, FileMode.Open, FileAccess.Read), 
                new XmlDictionaryReaderQuotas()); 

      _dictionary = (SortedDictionary<string, T>) dcs.ReadObject(reader, true); 
/* HERE! Apparently this fills in the Children property of the base class */ 
      // fill in Children 
      foreach (var pair in _dictionary) 
      { 
       pair.Value.Children = GetChildren(pair.Value.Id); 
      } 
      reader.Close(); 
      return _dictionary; 
     } 
    //... 
    } 

und wenn ich versuche, zur Laufzeit der Children Eigenschaft einer bestimmten PostCategory Instanz zuzugreifen, ist es null und die base.Children auf das richtige Wörterbuch der Kinder festgelegt wird, wie durch die GetChildren() Verfahren eingestellt.

Die Sache ist, mein Code beruht auf Überprüfung der PostCategory.Children-Instanz und weil es null ist, schlägt mein Code fehl.

Was ist der richtige Weg, um zu erreichen, was ich will (eine Basisklasse haben und den Typ einer Eigenschaft in der abgeleiteten Klasse ändern)?

Antwort

3

Vererbung für das Schlüsselwort new funktioniert nicht in der gleichen Weise wie virtualoverride Mitglieder, in dem es überhaupt nicht funktioniert. Wenn Sie über einen Verweis auf eine Basisklasse auf das Member zugreifen, wird auf das Member der Basisklasse zugegriffen, und das ausgeblendete Member wird vollständig umgangen. Im Falle einer ordnungsgemäßen Vererbung würde diese Art von Aufruf die abgeleiteten Klassen nach unten ziehen, wenn irgendeine von ihnen das Basiselement außer Kraft gesetzt hätte.

Wenn Sie richtiges Verhalten wollen, müssen Sie die Basiseigenschaft virtual und override in einer abgeleiteten Klasse machen.

Es scheint, als ob Sie versuchen, den abgeleiteten Typ spezifischer zu machen. Dies könnte möglicherweise unter Verwendung von Schnittstellen und co-variance erreicht werden.

+0

Ich kann den Typ einer Basiseigenschaft mit virtueller Überschreibung nicht ändern. Wird in Kovarianz schauen .. – mare

Verwandte Themen