2009-04-02 8 views
7

je suivre des cours:C# - classe générique à jeter sa classe de base non générique

public abstract class CustomerBase 
{ 
    public long CustomerNumber { get; set; } 
    public string Name { get; set; } 
} 

public abstract class CustomerWithChildern<T> : CustomerBase 
    where T: CustomerBase 
{ 
    public IList<T> Childern { get; private set; } 

    public CustomerWithChildern() 
    { 
     Childern = new List<T>(); 
    } 
} 

public class SalesOffice : CustomerWithChildern<NationalNegotiation> 
{ 
} 

Le SalesOffice est juste l'un des rares classes qui représentent différents niveaux de la hiérarchie des clients. Maintenant, je dois parcourir cette hiérarchie à partir d'un certain point (CustomerBase). Je ne peux pas comprendre comment mettre en œuvre sans utiliser la réflexion. Je voudrais mettre en œuvre quelque chose comme:

public void WalkHierarchy(CustomerBase start) 
    { 
     Print(start.CustomerNumber); 
     if (start is CustomerWithChildern<>) 
     { 
      foreach(ch in start.Childern) 
      { 
       WalkHierarchy(ch); 
      } 
     } 
    } 

Y at-il une chance que je pourrais obtenir quelque chose comme cela fonctionne?


La solution basée sur l'interface proposée a-childern I mis en œuvre:

public interface ICustomerWithChildern 
{ 
    IEnumerable ChildernEnum { get; } 
} 

public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern 
    where T: CustomerBase 
{ 
    public IEnumerable ChildernEnum { get { return Childern; } } 

    public IList<T> Childern { get; private set; } 

    public CustomerWithChildern() 
    { 
     Childern = new List<T>(); 
    } 
} 

    public void WalkHierarchy(CustomerBase start) 
    { 
     var x = start.CustomerNumber; 
     var c = start as ICustomerWithChildern; 
     if (c != null) 
     { 
      foreach(var ch in c.ChildernEnum) 
      { 
       WalkHierarchy((CustomerBase)ch); 
      } 
     } 
    } 

Répondre

2

Je crois que vous voulez faire la recherche pour la détermination de faire à la promenade une interface.

Alors peut-être ajouter une interface "IWalkable" qui expose les informations nécessaires pour faire la promenade, alors vous pouvez créer votre méthode de vérification pour voir si l'objet passé implémente l'interface.

2

"est" et "Comme" ne fonctionnent que sur les types génériques qualifiés.

Voir this MSDN discussion pour plus de détails, y compris les solutions de contournement.

La solution de contournement la plus courante que j'ai vu est d'ajouter une interface au mélange que votre CustomerWithChildren pourrait implémenter, et vérifier cette interface.

7

Vous pouvez déplacer la méthode WalkHierarchy vers la classe de base et la rendre virtuelle. L'implémentation de la classe de base ne traiterait que le nœud actuel. Pour la classe CustomerWithChildern<T>, le remplacement ferait une marche réelle.

+0

C'est la meilleure solution car il encapsule la mise en œuvre de la marche et fait exactement la bonne chose sans forcer l'appelant à être au courant des détails de mise en œuvre. – recursive

+0

Des éloges de la part de quelqu'un nommé "récursif". ;-) –

+0

Mon dernier grand projet .NET avait une exigence similaire, et John Saunders est comme moi. Fait beaucoup de choses tellement plus facile :) – OregonGhost

0

Explicitement avec cette méthode, pas. Cependant, vous pouvez obtenir la même fonctionnalité avec une interface. En fait, vous pourriez juste avoir votre classe générique implémenter IEnumerable. Il convient également de noter que votre classe devrait également avoir "où T: CustomerBase" afin d'assurer la sécurité du type.

1

Je pense que tout le monde rencontre ce "problème" lors de la première utilisation de classes génériques.

Votre premier problème est indiqué dans la formulation de votre question: un type générique ouvert n'est PAS la classe de base d'un type fermé. Il n'y a pas de relation OO ici, du tout. La vraie classe de base est CustomerBase. Un type générique "ouvert" est comme une classe semi-complétée; en spécifiant les arguments de type, il se "ferme", ce qui le rend complet.

Alors que vous pouvez faire:

Type t = typeof(CustomerWithChildern<>) 

la condition

typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>) 

sera toujours faux.

-Oisin

3

Essayez ceci:

if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>)) 
Questions connexes