2010-01-13 2 views
1

J'ai un problème et pas sûr de savoir comment le résoudre ..Héritant d'une classe qui est basée sur une classe générique, mais a besoin du type de classe de la classe dérivée

Considérez la classe:

public class BaseClass<T> 
{ 

    public T PreviousInstance { get; set; } 

} 

maintenant ma classe de données secondaires:

public class DataClass : BaseClass<DataClass> 
{ 
    public bool ABoolProperty { get; set; } 
} 

donc j'ai DataClass (qui est peuplée par un pont LINQ à WMI quand un objet change WMI) lorsque peuplé d'un événement de changement fournit l'une des données modifiées d les données précédentes avant la modification qui fonctionne très bien. J'ai maintenant une troisième classe:

public class DerivedDataClass : DataClass 
{ 
    public string AStringProperty { get; set; } 
} 

Mon problème est que DerviedDataClass.PreviousInstance est encore de DataClass de type, ce qui signifie que je reçois l'habitude des propriétés PreviousInstance qui sont déclarés dans DerivedDataClass.

J'ai pensé à DataClass-à-dire déclarant

public class DataClass<T> : BaseClass<T> 

qui permettrait aux propriétés de DerivedDataClass soient disponibles dans PreviousInstance. Cependant je dois encore être en mesure d'utiliser DataClass sur lui-même sans avoir à déclarer comme:

DataClass<DataClass<object>> 

juste pour faire fonctionner ce que je voudrais vraiment est d'avoir une version générique de la classe et une Version non générique, sans avoir à déclarer 2 classes séparées avec les mêmes propriétés.

Alors, des idées? :)

+0

Quel besoin avez-vous cela? –

+0

voir aussi: http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx –

Répondre

0

Vous pouvez essayer shadowing la propriété comme dans les domaines suivants:

public class DerivedDataClass : DataClass 
{ 
    new public DerivedDataClass PreviousInstance 
    { 
    get { return (DerivedDataClass)base.PreviousInstance; } 
    set { base.PreviousInstance = value; } 
    } 
} 

Si PreviousInstance n'est pas du type correct, vous obtiendrez une erreur. Remarque: vous ne pouvez pas faire référence à une instance de DerivedDataClass en tant que type de base DataClass, car il utilisera alors la version DataClass de PreviousInstance et contournera l'observation.

0

Eh bien ce que vous voulez n'est pas possible essentiellement parce que l'héritage multiple n'est pas autorisé.

Ce que vous pouvez faire est comptable sur la paramètre de type générique de la classe de base, comme dans

public class DataClass<T> : BaseClass<T> 

Selon ce que vous voulez réaliser, cela pourrait faire l'affaire pour vous. N'oubliez pas que les génériques ne sont pas destinés à être utilisés comme modèle de texte pour le code source.

0

Au moment où la seule façon que je peux voir est d'introduire une autre couche de la chaîne:

public abstract class AbstractDataClass<T> : BaseClass<T> 
{ 
    public bool ABoolProperty { get; set; } 
} 

public class DataClass : AbstractDataClass<DataClass> 
{ 
} 

public class DerivedClass : AbstractDataClass<DerivedClass> 
{ 
    public string AStringProperty { get; set; } 
} 

Bien que je l'avoue est très maladroit surtout quand vous commencez à entrer dans les niveaux croissants de la hiérarchie

2

Vous pouvez prendre l'approche suivante: - hiérarchies

public interface IPreviousInstance<T> 
{ 
    T PreviousInstance { get; set; } 
} 

public class DataClass : IPreviousInstance<DataClass> 
{ 
    public DataClass PreviousInstance { get; set; } 
    public bool ABoolProperty { get; set; } 
} 

public class DerivedDataClass : DataClass, IPreviousInstance<DerivedDataClass> 
{ 
    public new DerivedDataClass PreviousInstance { get; set; } 
    public string AStringProperty { get; set; } 
} 
+0

Je ne pense pas que les propriétés abstraites (comme PreviousInstance dans votre exemple) peuvent être implémenté en tant que propriétés automatiques. Toujours +1 car je pense que votre approche est la meilleure. – ShdNx

+0

Ce n'est pas une propriété abstraite, c'est une propriété d'interface. J'ai vérifié et le code compile. –

+0

Merci Adam, j'ai pensé à ce type de solution mais ma librairie doit être utilisée par mon équipe et si elle dérive ses propres données elle devra * savoir * implémenter l'interface, alors que ce dont j'ai besoin est un changement automatique le type de PreviousInstance. –

3

d'héritage sont là pour modéliser la notion de « je peux utiliser une instance d'une classe dérivée partout qu'une instance d'une classe de base est requise ", n'est-ce pas? Si vous avez une méthode qui prend un fruit, vous pouvez lui passer un Apple et savoir qu'il n'y aura pas de problèmes.

Simplifions votre code. Vous avez

class B<T> 
{ 
    public T Another { get; set; } 
} 
class Fruit : B<Fruit> {} 
class Apple : Fruit {} 
class Orange : Fruit {} 

Maintenant, Apple.Un autre est de type Fruit, pas de type Apple. Il doit être de type fruits, parce que vous pourriez avoir une méthode

void AddAnOrange(Fruit f) 
{ 
    f.Another = new Orange(); 
} 

Cela doit travailler même si vous passez dans un Apple - le contrat de fruit est un fruit que fait référence à tout autre fruit, pas "un fruit fait référence à un autre fruit de type plus dérivé qui n'est pas connu avant l'exécution".

Si vous avez besoin de modéliser la relation "Une pomme fait référence à une autre pomme, une orange fait référence à une autre orange", puis ne le faites pas en disant "Un fruit se réfère à un autre fruit"; ce n'est pas capturer la chose que vous voulez modéliser correctement, et vous causera juste la douleur plus tard.

0

Merci pour la réponse les gars, mais non des solutions tout à fait répondre à ce dont j'ai besoin. La bibliothèque que je suis en train d'utiliser doit être utilisée par mon équipe. Si elle a besoin de dériver ses propres données, elle doit être automatique pour ne pas avoir à avoir une connaissance approfondie de l'implémentation d'une interface. Ce que j'ai décidé de faire est d'ajouter une autre classe de décélération afin que le développeur final puisse utiliser le générique (pour les classes dérivées) ou non générique pour une utilisation directe dans leur application.

par exemple:

public class DataClass<T> : BaseClass<T> 
{ 
    public bool ABoolProperty { get; set; } 
} 

public class DataClass : DataClass<DataClass> 
{ 
} 
Questions connexes