Reputation: 1443
I have an interface to define my records\models
public interface IStockItem
{
string Code { get; set; }
string Description { get; set; }
decimal FreeStock { get; set; }
}
Is it best to put the actions into another interface?
public interface IStockExport
{
IEnumerable<IStockItem> GetAll();
IEnumerable<IStockItem> GetStockByCode(string code);
decimal GetFreeStock(string code);
}
public interface IStockImport
{
void CreateItem<IStockItem>;
}
Is there a better way to do this and make it more generic? so i can share the actions interfaces with other records\models?
The other records\models are SalesOrder, Customer, Address.
The overall idea is an Import\Export program, that will create\export sales orders in a number of different accounts packages via an API.
Upvotes: 2
Views: 86
Reputation: 109567
This is a common pattern, called the Repository Pattern
.
If you want to go down this route, you should create a base interface, Repository<T>
, for example:
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
IEnumerable<T> SearchFor(Func<T, bool> predicate);
IEnumerable<T> GetAll();
T GetById(int id);
}
You would make your IStockItem
implement an IEntity
interface so that it can provide an ID for GetById()
, for example:
public interface IEntity
{
int ID { get; }
}
Then you would implement the repository for a data type such as StockItem
by declaring the implementing class. It might start a bit like this:
public class Repository<T> : IRepository<T> where T : class, IEntity
{
protected Table<T> DataTable;
public Repository(DataContext dataContext)
{
DataTable = dataContext.GetTable<T>();
}
...
Your code that wanted to get at a repository for a stock item might look like this:
using (var dataContext = new StockItemDataContext())
{
var StockItemRepository = new Repository<IStockItem>(dataContext);
...
This may be overkill for what you want, but it is the general approach.
For full details see this excellent blog post.
Here's how you might start implementing this pattern for your case:
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
IEnumerable<T> SearchFor(Func<T, bool> predicate);
IEnumerable<T> GetAll();
T GetByCode(string code);
}
public interface IStockItem: IEntity
{
string Description { get; set; }
decimal FreeStock { get; set; }
}
public sealed class StockItem: IStockItem
{
public string Code { get; set; }
public string Description { get; set; }
public decimal FreeStock { get; set; }
}
public interface IEntity
{
string Code { get; }
}
public sealed class MyLowLevelDataAccess
{
public StockItem FindStockItem(string code)
{
return null; // Call your API here.
}
public void DeleteStockItem(string code)
{
// Call your API here.
}
public void InsertStockItem(StockItem item)
{
// Call your API here.
}
public IEnumerable<StockItem> FindAllItems()
{
return FindItemsMatching(x => true);
}
public IEnumerable<StockItem> FindItemsMatching(Func<StockItem, bool> predicate)
{
return null; // Call your API here and return all items matching the predicate.
}
}
public sealed class StockRepository: IRepository<StockItem>
{
private readonly MyLowLevelDataAccess _dataAccess;
public StockRepository(MyLowLevelDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public void Insert(StockItem entity)
{
_dataAccess.InsertStockItem(entity);
}
public void Delete(StockItem entity)
{
_dataAccess.DeleteStockItem(entity.Code);
}
public IEnumerable<StockItem> SearchFor(Func<StockItem, bool> predicate)
{
return _dataAccess.FindItemsMatching(predicate);
}
public IEnumerable<StockItem> GetAll()
{
return _dataAccess.FindAllItems();
}
public StockItem GetByCode(string code)
{
return _dataAccess.FindStockItem(code);
}
}
Upvotes: 4
Reputation: 2999
you can use a generic interface as well:
public interface IRecordExport<T> where T : IRecordBase
{
IEnumerable<T> GetAll();
IEnumerable<T> GetOneByCode(string code);
decimal GetFree(string code);
}
public interface IRecordImport<T> where T : IRecordBase
{
void CreateItem<T>();
}
Upvotes: 2
Reputation: 7944
You could, but it may not be necessary. Interfaces for method-based classes are best used where you want to have polymorphism related to implementation.
In your case, it seems that what you want is to be able to share common functionality (based on the IStockExport
interface) but also provide a polymorphic creation mechanism (based on IStockImport
).
I would suggest that you implement an abstract base class for IStockExport
which can be inherited for all the various types of IStockItem
(due to common interface) and then the derived classes should implement IStockExport
as each Create<IStockItem>()
implementation will be different but can be used in the same way due to common behaviour (always returns IStockItem
object).
Upvotes: 1