2009-04-02 9 views
7

He siguientes clases:C# - Reparto clase genérica a su clase base no genérico

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> 
{ 
} 

El SalesOffice es sólo una de las pocas clases que representan diferentes niveles de la jerarquía de clientes. Ahora necesito recorrer esta jerarquía desde algún punto (CustomerBase). No puedo entender cómo implementar sin usar la reflexión. Me gustaría implementar algo como:

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

¿Hay alguna posibilidad de que funcione algo así?


La solución basada en sugerida tiene-hijos también he implementado la interfaz:

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); 
      } 
     } 
    } 

Respuesta

2

Creo que quiere hacer la búsqueda de la determinación de hacer una interfaz a pie.

Así que tal vez agregue una interfaz "IWalkable" que exponga la información necesaria para realizar el recorrido, luego puede crear su método de comprobación para ver si el objeto pasado implementa la interfaz.

2

"es" y "como" sólo funcionan en los tipos genéricos completos.

Consulte this MSDN discussion para obtener detalles, incluidas las soluciones.

La solución más común que he visto es agregar una interfaz a la combinación que su CustomerWithChildren podría implementar y verificar esa interfaz.

7

Puede mover el método WalkHierarchy a la clase base y hacerlo virtual. La implementación de la clase base solo procesaría el nodo actual. Para la clase CustomerWithChildern<T>, la anulación haría una caminata real.

+0

Esta es la mejor solución, ya que encapsula la aplicación caminar y simplemente hace lo correcto sin obligar a la persona que llama a estar al tanto de los detalles de implementación. – recursive

+0

Alta alabanza de alguien llamado, "recursivo". ;-) –

+0

Mi último gran proyecto .NET tenía un requisito similar, y el de John Saunders es muy parecido al que hice. Hizo muchas cosas mucho más fácil :) – OregonGhost

0

Explícitamente con ese método, no. Sin embargo, puede lograr la misma funcionalidad con una interfaz. De hecho, podría hacer que su clase genérica implemente IEnumerable. También vale la pena señalar que su clase también debe tener "donde T: CustomerBase" para garantizar la seguridad del tipo.

1

Creo que todo el mundo golpea este "problema" cuando trabajamos por primera vez con clases genéricas.

Su primer problema se insinúa en el fraseo de su pregunta: un tipo genérico abierto NO es la clase base a una cerrada. No hay ninguna relación OO aquí, en absoluto. La clase base real es CustomerBase. Un tipo genérico "abierto" es como una clase a medio completar; especificando los argumentos de tipo "lo cierra", haciéndolo completo.

Mientras que usted puede hacer:

Type t = typeof(CustomerWithChildern<>) 

la condición

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

siempre será falsa.

-Oisin

3

Prueba esto:

if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>)) 
Cuestiones relacionadas