2015-12-03 2 views
0

J'ai déjà implémenté mes classes Repository, mais je me demande comment je peux refactoriser ses méthodes dans une classe de base qui peut être étendue par différents types de référentiels.Comment refactoriser la méthode en implémentation de classe de base générique?

J'ai commencé par créer la classe Repository de base ci-dessous, mais je ne suis pas sûr de la façon dont chaque méthode devrait être abstraite. Aussi, comment dois-je remplacer le type de modèle avec un espace réservé générique.

Dans ce example, les méthodes abstraites ne contiennent que la définition de la méthode et non la mise en œuvre:

public abstract Array sort(Array arr); 

Quelqu'un peut-il donner des conseils sur la façon de factoriser les méthodes pour les génériques?

J'ai commencé par créer la classe Repository de base abstraite, mais je suis resté bloqué en remplaçant les méthodes par des types génériques et des paramètres génériques.

L'exemple ci-dessous est Delete() qui est spécifique à CustomerModel. Il devrait être générique pour faciliter la réutilisation de la classe:

public abstract class BaseRepository 
{ 
    public async Task DeleteCustomer(CustomerModel customer) 
    { 
     var collection = StartConnection(); 
     var filter = Builders<CustomerModel>.Filter.Where(x => x.Id == customer.Id); 
     var result = await collection.DeleteOneAsync(filter); 
     customers.Remove(customer); 
    } 
} 

Ainsi, par exemple, c'est la classe complète CustomerRepository, qui contient les opérations CRUD pour ma db à distance. Les méthodes sont spécifiques au CustomerModel ce qui rend difficile de réutiliser:

public class CustomerRepository : ICustomerRepository 
{ 
    private static List<CustomerModel> customers = new List<CustomerModel>(); 

    static CustomerRepository() 
    { 
    } 

    private CustomerRepository() 
    { 

    } 

    public static CustomerRepository Instance 
    { 
     get 
     { 
      return instance; 
     } 
    } 

    public CustomerModel GetACustomer() 
    { 
     if (customers == null) 
      LoadCustomers(); 
     return customers.FirstOrDefault(); 
    } 

    public List<CustomerModel> GetCustomers() 
    { 
     if (customers.Count == 0) 
      LoadCustomers(); 
     return customers; 
    } 

    public CustomerModel GetCustomerById(ObjectId id) 
    { 
     if (customers == null) 
      LoadCustomers(); 
     return customers.Where(c => c.Id == id).FirstOrDefault(); 
    } 

    public CustomerModel GetCustomerByEmail(string email) 
    { 
     if (customers == null) 
      LoadCustomers(); 
     return customers.Where(c => c.Email == email).FirstOrDefault(); 
    } 

    public async Task DeleteCustomer(CustomerModel customer) 
    { 
     var collection = StartConnection(); 
     var filter = Builders<CustomerModel>.Filter.Where(x => x.Id == customer.Id); 
     var result = await collection.DeleteOneAsync(filter); 
     customers.Remove(customer); 
    } 

    public async Task AddCustomer(CustomerModel customer) 
    { 
     var collection = StartConnection(); 
     await collection.InsertOneAsync(customer); 
     customers.Add(customer); 
    } 

    public async Task UpdateCustomer(CustomerModel customer) 
    {   
     var collection = StartConnection(); 
     var filter = Builders<CustomerModel>.Filter.Where(x => x.Id == customer.Id); 

     collection.Find(filter).ToString(); 
     var result = await collection.ReplaceOneAsync(filter, customer, new UpdateOptions { IsUpsert = true }); 

     var index = customers.FindIndex(a => a.Id == customer.Id); 
     customers[index] = customer; 
    } 

    private void LoadCustomers() 
    { 
     var collection = StartConnection(); 

     try 
     { 
      customers = collection.Find(new BsonDocument()).ToListAsync().GetAwaiter().GetResult(); 
     } 
     catch (MongoException ex) 
     { 
      //Log exception here: 
      MessageBox.Show("A connection error occurred: " + ex.Message, "Connection Exception", MessageBoxButton.OK, MessageBoxImage.Warning); 
     } 
    } 

    private static IMongoCollection<CustomerModel> StartConnection() 
    { 
     var client = new MongoClient(connectionString); 
     var database = client.GetDatabase("orders"); 
     //Get a handle on the customers collection: 
     var collection = database.GetCollection<CustomerModel>("customers"); 
     return collection; 
    } 
} 

Répondre

3

Ne faites pas une classe de base contenant des méthodes spécifiques d'entité. Faire base générique du début.

public class Repository<T> where T : new() 
{ 
    public async Task<T> GetAsync(object key) 
    {} 

    public async Task DeleteAsync(T t) 
    {} 
} 

Ajoutez un niveau d'abstraction qui vous plaît. Si vous utilisez par exemple une sorte de ORM au sein de votre repo cela pourrait suffire.


Vous ne pouvez pas modifier les noms de méthode dans les classes héritées. Et il est plus simple d'utiliser des repos si tous ont les mêmes méthodes pour les opérations.

Si vous pouvez utiliser la base telle quelle, seuls les changements de paramètre Type sont appliqués. Donc, vous instanciez par exemple Repository<Customer> dans votre code.

Si la logique diffère entre les entités, alors par exemple. CustomerRepository : Repository<Customer> et mettre la logique là-bas. En outre, marquez la base comme abstraite et les méthodes abstraites/virtuelles.

+0

Le cours doit-il être marqué comme abstrait? Aussi, quand je prolonge la classe, est-il possible de changer les noms de méthodes hérités pour taper des instances spécifiques? –

+0

J'ai décidé d'implémenter l'interface IRepository au lieu de la classe, car cela facilite les tests unitaires. Les informations ci-dessus ont aidé avec le refactor et ce lien http://blog.falafel.com/implement-step-step-generic-repository-pattern-c/ –

+1

Pour les tests unitaires, vous pouvez utiliser «Moq», que vous pouvez obtenir via NuGet. Il vous permet de simuler et de câbler vos dépôts. –