2010-05-25 2 views
9

Je me demande s'il existe une meilleure façon d'aborder ce problème. L'objectif est de réutiliser le code. Disons que j'ai un contexte de données Linq-To-SQL et que j'ai écrit une classe de "style de référentiel" qui contient un grand nombre de méthodes dont j'ai besoin et qui expose IQueryables. (jusqu'à présent, pas de problème).Y at-il quelque chose de mal à avoir quelques méthodes privées exposant IQueryable <T> et toutes les méthodes publiques exposant IEnumerable <T>?

Maintenant, je construis une couche de service pour m'asseoir au-dessus de ce dépôt, la plupart des méthodes de service seront 1 < -> 1 avec des méthodes de référentiel, mais d'autres non. Je pense qu'un exemple de code illustrera mieux cela que les mots.

public class ServiceLayer 
{ 
    MyClassDataContext context; 
    IMyRepository rpo; 

    public ServiceLayer(MyClassDataContext ctx) 
    { 
     context = ctx; 
     rpo = new MyRepository(context); 
    } 

    private IQueryable<MyClass> ReadAllMyClass() 
    { 
     // pretend there is some complex business logic here 
     // and maybe some filtering of the current users access to "all" 
     // that I don't want to repeat in all of the public methods that access 
     // MyClass objects. 
     return rpo.ReadAllMyClass(); 
    } 

    public IEnumerable<MyClass> GetAllMyClass() 
    { 
     // call private IQueryable so we can do attional "in-database" processing 
     return this.ReadAllMyClass(); 
    } 

    public IEnumerable<MyClass> GetActiveMyClass() 
    { 
     // call private IQueryable so we can do attional "in-database" processing 
     // in this case a .Where() clause 
     return this.ReadAllMyClass().Where(mc => mc.IsActive.Equals(true)); 
    } 

    #region "Something my class MAY need to do in the future" 
    private IQueryable<MyOtherTable> ReadAllMyOtherTable() 
    { 
     // there could be additional constrains which define 
     // "all" for the current user 
     return context.MyOtherTable; 
    } 

    public IEnumerable<MyOtherTable> GetAllMyOtherTable() 
    { 
     return this.ReadAllMyOtherTable(); 
    } 

    public IEnumerable<MyOtherTable> GetInactiveOtherTable() 
    { 
     return this.ReadAllMyOtherTable.Where(ot => ot.IsActive.Equals(false)); 
    } 
    #endregion 

} 

Ce cas particulier n'est pas la meilleure illustration, puisque je pouvais appeler le dépôt directement dans la méthode GetActiveMyClass, mais nous allons présumer que mon IQueryable privé fait des traitements supplémentaires et la logique métier que je ne veux pas répliquer dans mes deux méthodes publiques.

Est-ce une mauvaise façon d'attaquer un problème comme celui-ci? Je ne pense pas que ce soit si complexe que cela justifie vraiment de construire une troisième classe entre le dépôt et la classe de service, mais j'aimerais avoir votre avis. Par exemple, supposons deux choses supplémentaires.

  1. Ce service va être exposé par WCF et que chacune de ces méthodes IEnumerable publiques appellerez un .Select(m => m.ToViewModel()) sur chaque collection retournée qui convertira à un POCO pour la sérialisation. Le service devra éventuellement exposer quelques context.SomeOtherTable qui ne seront pas enveloppés dans le dépôt.

Répondre

5

Je pense que c'est un bon modèle puisque vous pouvez créer des fonctions privées de base IQueryable qui peuvent être utilisées par les fonctions que vous exposer publiquement. De cette façon, vos méthodes publiques n'ont pas besoin de recréer une grande partie de la fonctionnalité commune que vos méthodes IQueryable effectuent et elles peuvent être étendues si nécessaire et différer l'exécution tout en cachant cette fonctionnalité publiquement.

Un exemple, par exemple, comment extraire X d'une table, ce qui peut nécessiter beaucoup de logique dont vous n'avez pas besoin dans sa forme brute. Vous disposez ensuite de cette méthode en tant que méthode privée, comme vous le faites dans votre exemple, puis la méthode publique ajoute les critères de finalisation ou les requêtes pour générer un ensemble de données utilisables pouvant différer d'une fonction à l'autre. Pourquoi continuer à réinventer la roue encore et encore ... il suffit de créer le design de base (que vous faites IQueryable) et laisser tomber le motif de bande de roulement nécessaire (votre IEnumerable public) :)

+1 pour une bonne conception IMO.

+0

C'est ce que j'espérais entendre, merci. J'espérais obtenir quelques points de vue oposing aussi bien. – Nate

+0

@Nate Bross Je ne peux pas penser à des points opposés à faire, donc vous devriez être sur la bonne voie :) – Kelsey

+0

Je suppose que je cherchais quelqu'un à dire, 'non, vous devriez vraiment faire xyz à la place.» Pas parce que je Je pense que j'ai trouvé ça mauvais, je veux juste voir une bonne affaire contre elle pour voir si ce que j'ai se lève bien ou pas. – Nate

Questions connexes