2012-05-08 5 views
4

J'essaie d'implémenter la meilleure réutilisabilité du code. Le problème est que je ne peux pas accéder à la méthode de base située dans la classe de base de résumé du programme principal à travers le référentiel.C# .NET Design Pattern numéro

Si vous parcourez l'exemple ci-dessous, vous verrez un exemple de code de ma situation. Donc, ma question est comment puis-je accéder à des méthodes situées dans la classe abstraite de base à partir du programme principal.

Classes/Interfaces

public abstract class BaseEntity 
{ 
    public override abstract String ToString(); 
} 

public abstract class BaseClass<T> where T : BaseEntity 
{ 
    public T GetById(int id) 
    { 
     //Dummy Code 
     return new T(); 
     // 
    } 
} 

public interface IFooRepository 
{ 
    IList<Foo> GetOrderedObjects(); 
} 

public interface FooRepository : BaseClass<Foo>, IFooRepository 
{ 
    public IList<Foo> GetOrderedObjects() 
    { 
     //GetById method is accessible from the repository - Fine 
     var obj = this.GetById(5); 

     //Dummy Code 
     return new List<Foo>(); 
     // 
    } 
} 

// principal App

public class void Main() 
{ 
    private IFooRepository _fooRepository; 

    public void ProgramStartsHere() 
    { 
     //This is ok. 
     var list = _fooRepository.GetOrderedObjects(); 

     //Problem is here - GetById method is not accessible from the main program through the FooRepository 
     var obj = _fooRepository.GetById(10); 
    } 
} 
+1

Etes-vous sûr que votre code est OK? Je veux dire que cette interface avec la méthode implémentée est fausse. http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx – besworland

+0

interface publique FooRepository: BaseClass comment cela peut-il compiler?vous ne pouvez pas dériver une interface à partir d'une classe –

Répondre

10

GetById n'est pas défini dans l'interface

Je voudrais faire un

public interface IBaseRepository<T> where T : BaseEntitiy { 
T GetById<T>(int id); 
} 

Puis BaseClass implémente IBaseRepository<T>

et IFooRepository hérite de IBaseRepository<Foo>

EDIT:

Un exemple complet, similaire à @Olivier J-D, avec une idée (peut-être mal), que GetOrderedObject peuvent être identiques pour toutes les entités.

public abstract class BaseEntity 
{ 
    public override abstract String ToString(); 
} 

//all generic methods 
public interface IRepositoryBase<T> 
    where T : BaseEntity, new() 
{ 
    T GetById(int id); 
    IList<T> GetOrderedObjects(); 

} 

//all methods specific to foo, which can't be in a generic class 
public interface IFooRepository :IRepositoryBase<Foo> 
{ 
    void Update(Foo model); 
} 

//implementation of generic methods 
public abstract class BaseClass<T> : IRepositoryBase<T> 
    where T : BaseEntity, new() // ===> Add new() constraint here 
{ 
    public T GetById(int id) 
    { 
     return new T(); 
    } 
    public IList<T> GetOrderedObjects() { 
     var obj = this.GetById(5); 

     //Dummy Code 
     return new List<Foo>(); 
     // 
    } 
} 

//implementation of Foo specific methods 
public class FooRepository : BaseClass<Foo>, IFooRepository 
{ 
    public void Update(Foo model) { 
    //bla bla 
    } 
} 
+0

Je seconde cette réponse! C'est ainsi que je veux le faire .. nettoyer et réduire le code redondant .. –

+0

Avez-vous un exemple complet? Parce que je suis confus:/ – user1382086

+0

Fait, ou regarder @ Univier un, ils peuvent tous deux être utilisés, en fonction de vos besoins spécifiques ... –

-3

IFooRepository ne hérite pas de BaseClass, de sorte que vous devez jeter _fooRepository à FooRepository. Ensuite, vous pouvez accéder à GetById()

-5

Jetez-le à la classe de base.

var obj = ((BaseClass<Foo>)_fooRepository).GetById(10); 
+9

Lancer est toujours une mauvaise idée - dans la plupart des cas, l'utiliser montre que votre structure OOP est fausse .. –

3

Votre _fooRepository hérite de IFooRepository, pas FooRepository, donc il n'a pas accès à GetById(10);

4

Ajouter une nouvelle interface qui déclare la méthode GetById et laissez-IFooRepository et BaseClass<T> Hériter de lui. Vous devrez également ajouter un paramètre de type générique à IFooRepository. (Je renomme IFooRepository à IRepository<T>, car il est générique maintenant.)

public abstract class BaseEntity 
{ 
    public override abstract String ToString(); 
} 

public interface IRetriever<T> 
    where T : BaseEntity, new() 
{ 
    T GetById(int id); 
} 

public interface IRepository<T> : IRetriever<T> 
    where T : BaseEntity, new() 
{ 
    IList<T> GetOrderedObjects(); 
} 

public abstract class BaseClass<T> : IRetriever<T> 
    where T : BaseEntity, new() // ===> Add new() constraint here 
{ 
    public T GetById(int id) 
    { 
     return new T(); 
    } 
} 

public class FooRepository : BaseClass<Foo>, IRepository<Foo> 
{ 
    public IList<Foo> GetOrderedObjects() 
    { 
     var obj = this.GetById(5); 
     return new List<Foo>(); 
    } 
} 

Cela fonctionne bien alors

IRepository<Foo> _fooRepository = new FooRepository(); 
var list = _fooRepository.GetOrderedObjects(); 
var obj = _fooRepository.GetById(10); 
+0

Nice one ... Mais une remarque: quel est l'intérêt de deux interfaces distinctes dans votre exemple? Si tout est générique, IList GetOrderedObjects() doit être dans IRetriever , non? et GetOrderedObject devrait être dans BaseClass car il est également générique? –

+0

@ RaphaëlAlthaus: Une interface distincte est logique, puisque 'BaseClass ' implémente 'GetById'. Bien que cela fonctionnerait sans cela. Si 'IRepository ' déclarait 'GetById' directement,' FooRepository' l'implémenterait automatiquement en l'héritant de 'BaseClass '. Cependant, il me semble plus propre. –

+1

@ RaphaëlAlthaus: C'était la décision de user1382086 d'implémenter 'GetById' dans' BaseClass 'et' GetOrderedObject' dans 'FooRepository'. Probablement parce qu'il a plusieurs dépôts qui peuvent hériter de la même implémentation de 'GetById' mais qui ont besoin d'implémenter différentes méthodes' GetOrderedObjects'. –

3

Vous devez exposer la méthode GetById dans votre interface référentiel.

public interface IFooRepository 
{ 
    IList<Foo> GetOrderedObjects(); 
    Foo GetById(int id); 
} 

vous pouvez également utiliser une contrainte de paramètre de type, comme indiqué par Raphaël Althaus

+0

Remplacer T par Foo! –

+0

Oups! Je vous remercie! – JotaBe

+0

remplacer T par Foo, pas Foo par T;) –