2009-08-07 6 views
1

J'ai une petite question. Quelque chose semble vraiment faux avec ce code. Je veux profiter des génériques et des délégués et peut-être même des délégués génériques s'il y a lieu. Je travaille avec des api générés par code et les objets générés sont très similaires. Je vois qu'ils implémentent tous une interface donc je devais essayer de créer une classe avec quelques méthodes pour gérer les différents scénarios. Voici un exemple de code. Cela semble juste mal à tant de niveaux. S'il vous plaît dites-moi comment je peux améliorer ce code. Un petit conseil de refactoring si vous voulez. Et par tous les moyens déchirer en lambeaux. Je veux mieux coder et apprendre à faire les choses correctement.Affecter un délégué en fonction d'un type?

private delegate IsomeEntity DisplayDelegate(IsomeEntity display); 

public IsomeEntity Display<T>() 
{ 
    DisplayDelegate _del = null; 
    IsomeEntity display = factory.CreateObject(typeof(T).Name); 

    if (display.GetType() == typeof(ADisplayEntity)) 
     _del = ADisplayEntity; 

    if (display.GetType() == typeof(BDisplayEntity)) 
     _del = BDisplayEntity; 

    if (display.GetType() == typeof(CDisplayEntity)) 
     _del = CDisplayEntity; 


    return _del(display); 
} 

public ADisplayEntity ADisplayEntity(IsomeEntity display) 
{ 
    ADisplayEntity ade = display as ADisplayEntity; 

    try 
    { 
     ADisplay o = new ADisplay(); 
     ADisplayEntity response = o.ADisplay(ade); 
     return response; 
    } 
    catch (Exception ex) 
    { 
     Exception newEx; 
     if (someExceptionHandler.HandleException(ex, this, out newEx)) 
      throw newEx; 
    } 

    return null; 
} 

public BDisplayEntity BDisplayEntity(IsomeEntity display) 
{ 
    BDisplayEntity dde = display as BDisplayEntity; 

    try 
    { 
     BDisplay o = new BDisplay(); 
     BDisplayEntity response = o.BDisplay(bde); 
     return response; 
    } 
    catch (Exception ex) 
    { 
     Exception newEx; 
     if (someExceptionHandler.HandleException(ex, this, out newEx)) 
      throw newEx; 
    } 

    return null; 
} 

Répondre

0

Vous pouvez passer les délégués et les fonctions lambda que les valeurs génériques, donc quelque chose comme ceci:

public ISomeEntity Display<T>(Func<T, ISomeEntity> conversion) 
{ 
    IsomeEntity display = factory.CreateObject(typeof(T).Name); 
    return conversion(display); 
} 

appel, ce serait alors:

var myNewEntity = Display( 
    x => ADisplay.GetADisplay(x as ADisplayEntity)); 

Et ainsi de suite.

Je ne suis pas tout à fait sûr de ce que vous essayez de faire - donc mon code n'est probablement pas tout à fait correct, mais il devrait vous donner une idée de la façon dont vous pouvez passer lambdas.

Vous pouvez même les stocker dans des dictionnaires et les rechercher.

+0

Je pense qu'il veut que le code dans la méthode d'affichage de sorte qu'il n'a pas de préciser chaque fois qu'il veut un ISomeEntity – Randolpho

0

Ok, si je vous suis correctement, ADisplayEntity et BDisplayEntity sont des classes générées qui ressemblent à peu près au même, non? Et vous essayez de créer une sorte de méthode de délégué générique (celle que vous avez appelée Display<T>) qui permet à l'appelant de spécifier le type d'entité d'affichage qu'il souhaite, une seule interface que vous avez créée que les entités implémentent, oui ? Je suppose que les classes ADisplay et BDisplay n'implémentent pas une méthode commune Display(), c'est pourquoi vous avez les appels à ADisplay et BDisplay. Hmm ... ce sont le même nom que la classe. Faute de frappe? Ce que vous avez énuméré ne compilera même pas.

Je pense qu'un meilleur exemple est nécessaire. Je me rends compte que vous essayez d'assainir votre code, mais peut-être un vrai code avec des changements de nom pourrait être mieux. Je voudrais voir ce que ADisplay, BDisplay, ADisplayEntity et BDisplayEntity sont vraiment. Cela dit, si les différentes classes A/BDisplay et A/BDisplayEntity sont vraiment différentes que vous ne pouvez pas consolider ces méthodes déléguées en une seule méthode, alors vous faites à peu près la seule chose que vous pouvez faire pour atteindre votre objectif initial.

Peut-être avec plus d'informations je peux fournir une meilleure réponse, mais je ne vois pas grand chose à refactoriser ici. À part les noms de vos méthodes étant les mêmes noms que les classes qu'ils instancient et vos appels à une méthode qui est le même nom que la classe.

0

pourquoi pas quelque chose comme simple? Pourquoi avez-vous besoin delegates..etc

public static ISomeEntity DisplayEntity(ISomeEntity display) 
{ 

     ISomeEntity result; 
      if (entity is ADisplayEntity) 
      { 
       ADisplay disp = new ADisplay(); 
       result = disp.ADisplayFunc(); 
      } 
      if(entity is BDisplayEntity) 
      { 
       BDisplay disp = new BDisplay(); 
       result = disp.BDisplayFunc(); 
      } 

    return result; 
} 

Bien sûr, il serait plus logique si vous pourriez avoir votre AAffichez et BAffichez suivre également une interface, comme IDisplay alors vous avez juste besoin de revenir IDisplay.Affichage (ISomeEntity)

à suivre sur que vous pouvez envelopper vos écrans comme ça ..

public interface IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity); 
} 

public class AWrappedDisplay: IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     ADisplay disp = new ADisplay(); 
     return disp.ADisplayFunc(entity); 
    } 

} 

public class BWrappedDisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     BDisplay disp = new BDisplay(); 
     return disp.BDisplayFunc(entity); 
    } 

} 

public static IDisplay Factory(Type t) 
     { 
      IDisplay disp = null; 
      if (t == typeof(ADisplayEntity)) 
       disp = new AWrappedDisplay(); 

      if (t == typeof(BDisplayEntity)) 
       disp = new BWrappedDisplay(); 

      return disp; 
     } 

et vous pouvez appeler votre DisplayEntity comme celui-ci

public static ISomeEntity DisplayEntity(ISomeEntity display) 
    { 
     IDisplay disp = Factory(display.GetType()); 
     ISomeEntity newDisplayEntity = disp.Display(display); 

     return newDisplayEntity; 
    } 
0

Si vous voulez généraliser ces méthodes que vous pourriez faire quelque chose comme ceci:

private delegate IsomeEntity DisplayDelegate<T>(IsomeEntity display); 

    public IsomeEntity DisplayMethod<T>() where T : IsomeEntity 
    { 
     DisplayDelegate<T> _del = new DisplayDelegate<T>(DoDisplay<T>); 
     IsomeEntity entity = factory.CreateObject(typeof(T).Name); 

     return _del(entity); 
    } 

    public IsomeEntity DoDisplay<T>(IsomeEntity entity) 
    { 
     try 
     { 
      Display<T> o = new Display<T>(); 
      Entity<T> response = o.Display(entity); 
      return response; 
     } 
     catch (Exception ex) 
     { 
      if (someExceptionHandler.HandleException(ex, this, out newEx)) 
       throw newEx; 
     } 
    } 

Dans cette situation, le délégué n'est vraiment pas nécessaire et vous pouvez appeler le DoDisplay directement.

public IsomeEntity DisplayMethod<T>() where T : IsomeEntity 
    {    
     IsomeEntity entity = factory.CreateObject(typeof(T).Name); 

     return DoDisplay<T>(entity); 
    } 

    public IsomeEntity DoDisplay<T>(IsomeEntity entity) 
    { 
     try 
     { 
      Display<T> o = new Display<T>(); 
      Entity<T> response = o.Display(entity); 
      return response; 
     } 
     catch (Exception ex) 
     { 
      if (someExceptionHandler.HandleException(ex, this, out newEx)) 
       throw newEx; 
     } 
    } 
+1

je vois ce que vous faites ici, mais votre exemple wouldnt compiler, quel type exactement est * o *, et comment * o * ont * o.Display (entité) * –

+0

J'ai basé l'exemple sur l'OP, et l'OP avait "ADisplay" et "BDisplay". Je viens de le renommer en "Display" car il était générique. L'exemple est pour la syntaxe et la conception, il n'inclut pas tout le nécessaire pour réellement compiler, construire et exécuter. Les détails de la mise en œuvre sont laissés à l'utilisateur. –

0

Je vais supposer que puisque vous avez mentionné ce genre de choses a été généré automatiquement que la modification ISomeEntity est la fenêtre (sinon je vous suggère d'ajouter une méthode d'affichage() pour ISomeEntity puis simplement en l'appelant directement sur l'entité via l'interface, chaque entité implémenterait sa propre version de Display()). Donc, si je comprends ce que votre code essaie de faire correctement (ce n'est pas vraiment clair), je suggèrerais de créer une interface IDisplay, dont ADisplay et BDisplay en hériteraient. Cette interface aurait une méthode Display() qui prend ISomeEntity et renvoie ISomeEntity. Toutefois, si ADisplay.Display (ISomeEntity) reçoit un BDisplayEntity vous lèveriez une exception.

Puis, je créerais un IDictionary que vous stockeriez comme un champ dans la classe qui a cette méthode d'affichage principale (je vais l'appeler Displayer). Ce dictionnaire stocke ce que IDisplay doit utiliser pour chaque type (ie typeof (ADisplayEntity) -> new ADisplay()).

Vous pouvez ensuite ajouter votre méthode d'affichage principale à Displayer, mais en la faisant retourner un T générique, puisque T est le type que vous créez et renvoyez. Cette méthode recherche quel IDisplay il a besoin et l'utilise sur l'ISomeEntity créé en usine et le résultat est retourné. L'utilisation du dictionnaire signifie que vous n'obtenez pas un lot merdique d'instructions if et que vous pouvez facilement ajouter plus d'IDisplays en ajoutant simplement au dictionnaire.

Voici mon code, qui compile dans VS2008.

public interface ISomeEntity 
{ 

} 

public class EntityFactory 
{ 
    public ISomeEntity CreateObject(string name) 
    { 
     //Do factory stuff here 
     return null; 
    } 
} 

public class ADisplayEntity : ISomeEntity 
{ 
} 



public class BDisplayEntity : ISomeEntity 
{ 
} 

public interface IDisplay 
{ 
    ISomeEntity Display(ISomeEntity entity); 
} 

public class ADisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     ADisplayEntity aEntity = entity as ADisplayEntity; 
     if (aEntity == null) 
      throw new ArgumentException("Wrong type"); 

     //Do whatever happens when you convert parameter entity into a 
     //"response" ADisplayEntity. I'm just returning a new 
     //ADisplayEntity to make it compile for me 
     return new ADisplayEntity(); 
    } 
} 

public class BDisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     BDisplayEntity bEntity = entity as BDisplayEntity; 
     if (bEntity == null) 
      throw new ArgumentException("Wrong type"); 

     //Do whatever happens when you convert parameter entity into a 
     //"response" BDisplayEntity. I'm just returning a new 
     //BDisplayEntity to make it compile for me 
     return new BDisplayEntity(); 
    } 
} 



public class Displayer 
{ 
    private IDictionary<Type, IDisplay> displayers; 
    private EntityFactory factory; 


    public Displayer() 
    { 
     factory = new EntityFactory(); 
     displayers = new Dictionary<Type, IDisplay> 
         { 
          { typeof(ADisplayEntity), new ADisplay() }, 
          { typeof(BDisplayEntity), new BDisplay() } 
         }; 
    } 


    public T Display<T>() where T : class, ISomeEntity 
    { 
     T entity = factory.CreateObject((typeof(T).Name)) as T; //Type-safe because of the factory 
     IDisplay displayer = displayers[typeof(T)]; 
     return displayer.Display(entity) as T; //Typesafe thanks to each IDisplay returning the correct type 
    } 
} 
Questions connexes