C# > Object-Oriented Programming (OOP) > Polymorphism > Interfaces and Implementation
Generic Interface Implementation: Repository Pattern
This snippet demonstrates how to use a generic interface to implement the Repository pattern. It provides a reusable interface for data access operations, promoting code reusability and testability.
Generic Interface Definition: IRepository
This code defines a generic interface named IRepository
. The
indicates that this is a generic interface, which can work with different types. The where T : class
constraint specifies that T
must be a reference type (i.e., a class). This interface defines common data access operations like GetById
, GetAll
, Add
, Update
, and Delete
. By using a generic interface, you can create repositories for different entities without duplicating code.
public interface IRepository<T> where T : class
{
T GetById(int id);
IEnumerable<T> GetAll();
void Add(T entity);
void Update(T entity);
void Delete(T entity);
}
Concrete Implementation: ProductRepository
This code defines a class named ProductRepository
that implements the IRepository
interface. It provides concrete implementations for the data access operations, specifically for Product
entities. This example uses a simple List
to simulate a database. In a real-world application, you would use a database context (e.g., Entity Framework) to interact with a database. The key point is that it fulfills the contract defined by the interface for the Product
type.
public class ProductRepository : IRepository<Product>
{
private List<Product> _products = new List<Product>(); // Simulate a database
private int _nextId = 1;
public Product GetById(int id)
{
return _products.FirstOrDefault(p => p.Id == id);
}
public IEnumerable<Product> GetAll()
{
return _products;
}
public void Add(Product entity)
{
entity.Id = _nextId++;
_products.Add(entity);
}
public void Update(Product entity)
{
var existingProduct = _products.FirstOrDefault(p => p.Id == entity.Id);
if (existingProduct != null)
{
// In a real implementation, you would update the properties of the existing product
_products.Remove(existingProduct);
_products.Add(entity);
}
}
public void Delete(Product entity)
{
_products.Remove(entity);
}
}
Product Class Definition
This code defines a simple Product
class with properties for Id
, Name
, and Price
. This is the entity that the ProductRepository
manages.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Usage Example
This code demonstrates how to use the ProductRepository
. It creates an instance of ProductRepository
and adds a new Product
. Then, it retrieves the product by its ID and prints its name and price.
IRepository<Product> productRepository = new ProductRepository();
Product newProduct = new Product { Name = "Laptop", Price = 1200 };
productRepository.Add(newProduct);
Product retrievedProduct = productRepository.GetById(1);
Console.WriteLine($"Product Name: {retrievedProduct.Name}, Price: {retrievedProduct.Price}");
Benefits of Using a Generic Repository
IRepository
interface can be used with different entity types, reducing code duplication.IRepository
interface for unit testing.
Concepts Behind the Snippet
This snippet demonstrates the following concepts:
Real-Life Use Case
In a large enterprise application, you might have multiple entities (e.g., Customer, Order, Product). Using a generic repository pattern, you can create a consistent and reusable data access layer for all entities, simplifying maintenance and reducing code duplication.
When to Use Them
The repository pattern is particularly useful when:
Alternatives
Pros
Cons
FAQ
-
What is the purpose of the
where T : class
constraint?
Thewhere T : class
constraint specifies that the type parameterT
must be a reference type (i.e., a class). This ensures that the repository only works with entities that are classes, not value types (e.g., int, bool). -
How can I implement a repository with Entity Framework?
You would create a class that implements theIRepository
interface and uses anDbContext
to interact with the database. The methods in the repository would use Entity Framework methods (e.g.,dbSet.Find
,dbSet.Add
,dbSet.Remove
) to perform data access operations.