I want to design an interface has the function to do mapping from Entity object to Form object
public interface IFormToEntityMapper
{
TEntity Map(TForm tForm);
}
and vice versa.
public interface IEntityToFormMapper
{
TForm Map(TEntity tEntity);
}
I have the question if I should define these two functions in one interface and separate them to different interfaces. If I put them into one interface, does that violate the single responsibility principle?
One option is to use Generics for the Interface:
public interface IMapper<TSource, TDestination> {
public TDestination Map(TSource source);
}
public class FormToEnityMap : IMapper<Form, Entity> {
public Entity Map(Form source){
}
}
public class EntityToFormMap : IMapper<Entity, Form> {
public Form Map(Entity source) {
}
}
Related
I want to cast the type of the interface definition in the C# implementation.
ex):
public interface IModel
{
IModel Apply(IModel from);
}
public class XxxModel: IModel
{
public XxxModel Apply(XxxModel from) // <- Interface Implementation Error
{
}
}
As a Countermeasure:
public class XxxModel: IModel
{
public IModel Apply(IModel from)
{
if (from.GetType() != typeof(XxxModel))
throw new ArgumentException("Type Not Matched.");
...
}
}
However, this leaves open the possibility of errors during execution.
I want to make the types of the argument and return value an implementation class.
What would be the best way?
You can create a generic interface, using the implementation class for its generic type:
public interface IModel<T> where T: IModel<T>
{
T Apply(T from);
}
public class XxxModel: IModel<XxxModel>
{
public XxxModel Apply(XxxModel from) // All good
{
}
}
partial class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
}
My generic repository implements a common set of methods for TEntity like
public TEntity Get(int id)
{
return _context.Set<TEntity>()
.Find(id);
}
public TEntity Get(Expression<Func<TEntity, bool>> predicate)
{
return _context.Set<TEntity>()
}
which I can access like
Repository<User>().Get();
Many repositories does the same set of operation, so it is beneficial but now I want to extend Repository<User> to support some additional behavior.
partial class Repository<User> : IRepository<User>
{
public user DoMagicFunction()
{
}
}
so that I can use the repository like
Repository<User>().DoMagicFunction();
how can I extend the same generic class for Some Tentity to extend new behaviour instead of modifying it.
I could have done the same like creating another UserRepository to support new feature, but the accessor would become
UserRepository.DoMagicFunction();
but I want it to be like
Repository<User>().DoMagicFunction();
You can use an extension method:
public static class ExtensionMethods {
public static User DoMagicFunction(this Repository<User> repository) {
// some magic
return null; //or another user
}
}
This will thus add the function in a syntactically nice way to Repository<User> objects.
In case you want to support it not only for Users, but for subclasses of Users as well, you can make the function generic:
public static class ExtensionMethods {
public static TEntity DoMagicFunction<TEntity>(this Repository<TEntity> repository)
where TEntity : User {
// some magic
return null; //or another TEntity
}
}
C# has a language feature called Extension Methods, you probably are using them from the .NET framework without knowing (e.g. the linq extensions methods). It's common to extend your classes or even your interfaces with extension methods without breaking the functionality of your code. Here is an example for your case.
Suppose you have a generic IRepository interface:
public interface IRepository<TEntity> where TEntity : class, IEntity
{
IQueryable<TEntity> Entities { get; }
}
This interface adheres to the SOLID principles, especially the O and I principle.
Now suppose IEntity looks like this:
public interface IEntity
{
int Id { get; }
}
Now you could perfectly imagine an often reusable extension method like this:
public static class RepositoryExtensions
{
// similar to your MagicFunction
public static TEntity GetById<TEntity>(this IRepository<TEntity> repository, int id)
where TEntity : class, IEntity
{
return repository.Entities.Single(entity => entity.Id == id);
}
}
In a similar manner you could also extend your Repository class
public static class RepositoryExtensions
{
public static TEntity GenericMagicFunction<TEntity>(this Repository<TEntity> repository)
{
//do some stuff
}
}
You can now consume that like this:
var repository = new Repository<User>();
var user = repository.GenericMagicFunction();
You could also limit your extension method:
public static class RepositoryExtensions
{
public static User DoMagicFunction(this Repository<User> repository)
{
//do some stuff
}
}
But doing this will defeat it's purpose, you could rather just implement this in the Repository<User> class.
If your system and architecture uses Dependency Injection, you're probably injecting an IRepository<User> to your consuming classes. So the first or second extension method examples I've provided would make the most sense.
If you want to extend any repository you can do it like this.
public static class RepositoryExtension
{
public static void MagicMethod<TEntity>(this IRepository<TEntity> repo) where TEntity: class
{
....
}
}
For a specific repository (eg User repository) you can use a similar process
public static class RepositoryExtension
{
public static void MagicMethod(this IRepository<User> repo)
{
....
}
}
Extension methods are not the way to go, because the code that implements the method can only access public/internal members of the class they extend and you are likely to want your repository's DataContext to be private.
In my opinion, your approach needs to be changed slightly.
What if in the future you want to add a Delete method to your generic repository, but you have some entities that should never be deleted? You'll end up with an instance of a repository for something like PurchaseOrder that you'll either have to remember to never call delete on or you will have to create a descendant of Repository<T> that throws an InvalidOperationException if called. Both of which are poor implementations.
Instead, you should delete your IRepository<T> interface completely. Keep your Repository<T> class, but explicitly define a repository interface for every entity that only has the methods you require.
public class Repository<TKey, TEntity>......
{
public TEntity Get<TEntity>(TKey key)....
public void Delete(TEntity instance)....
...etc...
}
public interface IPurchaseOrderRepository {
PurchaseOrder Get(int orderNumber);
// Note: No delete is exposed
}
MyDependencyInjection.Register<IPurchaseOrderRepository, Repository<PurchaseOrder, int>>();
When you need additional methods on your repository you add them to your IPurchaseOrderRepository and create a descendant of Repository<T>
public interface IPurchaseOrderRepository {
PurchaseOrder Get(int orderNumber);
void DoSomethingElse(int orderNumber);
}
public class PurchaseOrderRepository: Repository<PurchaseOrder, int> {
public void DoSomethingElse(int orderNumber) {.......}
}
MyDependencyInjection.Register<IPurchaseOrderRepository, PurchaseOrderRepository>();
Extension method is a best choice for this case.
Note: I have not checked but you should check Dependency Injection still works well as normal.
You can use below code for testing:
public class Employee
{
}
public class User
{
}
public interface IRepo<TEntity> where TEntity : class
{
TEntity Get(int id);
DbSet<TEntity> Get(Expression<Func<TEntity, bool>> predicate);
DbContext GetContext();
}
public class Repo<TEntity> : IRepo<TEntity> where TEntity : class
{
DbContext _context;
public TEntity Get(int id)
{
return _context.Set<TEntity>()
.Find(id);
}
public DbSet<TEntity> Get(Expression<Func<TEntity, bool>> predicate)
{
return _context.Set<TEntity>();
}
public DbContext GetContext()
{
return _context;
}
}
public static class RepoExtensions
{
public static ChangeTracker DoMagic(this Repo<User> userRepo)
{
return userRepo.GetContext().ChangeTracker;
}
}
public static class Test
{
public static void DoTest()
{
Repo<User> repoUser = new Repo<User>();
repoUser.DoMagic();
Repo<Employee> repoEmployee = new Repo<Employee>();
//repoEmployee.DoMagic();
}
}
In order to use dependency injection in .NET Core, we've built a bunch of repository interfaces for our controllers to use for database interactions.
We have a EntityBase class that has some methods in it, and our generic repository interface uses that base class like: IRepository<T> where T : EntityBase.
I want to add a more specific TaggedEntityBase class that extends EntityBase to represent the fact that we have some Entities which we want to filter by tags. I want TaggedEntityBase to have an abstract property which I can use in my controller so that I can abstract out and reuse the filtering method.
So what I want is something like this, but I think I want ITaggedRepository to also inherit from IRepository so that a class implementing ITaggedRepository is guaranteed to have a ListAll method and a ListWithTags method:
public class EntityBase { }
public abstract class TaggedEntityBase : EntityBase
{
public string TagIDs { get; }
}
public interface IRepository<T> where T : EntityBase
{
IEnumerable<T> ListAll();
}
public interface ITaggedRepository<T> where T : TaggedEntityBase
{
IEnumerable<T> ListWithTags(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
}
I'm fairly certain that I've just thoroughly confused myself by pursuing this line of thinking, but I'm not sure how to do what I really want here. I know I need to keep things abstract for dependency injection, but I feel like I'm butting up on the edge of what's possible with interfaces.
Is there a better line of thinking that will get me where I'm trying to go?
You can go ahead and inherit from IRepository<T>:
public interface ITaggedRepository<T> : IRepository<T> where T : TaggedEntityBase
{
IEnumerable<T> ListWithTags(Expression<Func<T, bool>> predicate);
}
At some point you may into trouble if your TaggedEntity is not really an abstraction. Say you have NamedEntities also and some are Tagged.
Now you have a INamedRepository, ITaggedRepository and a INamedTaggedRepository (you'll run into similar issues on your base entity).
You could do a more trait like thing like:
public class EntityBase {}
public interface ITagged
{
string TagIDs { get; }
}
public interface INamed
{
string Name { get; }
}
public class Book : EntityBase, ITagged, INamed
{
public string TagIDs { get; set; }
public string Name { get; }
}
public interface IRepository<T> where T : EntityBase
{
IEnumerable<T> ListAll();
}
public interface IQueryTags<T> where T : ITagged
{
IEnumerable<T> ListWithTags(Expression<Func<T, bool>> predicate);
}
public interface IQueryByName<T> where T : INamed
{
T GetByName(string name);
}
public interface IBookRepository : IRepository<Book>, IQueryTags<Book>, IQueryByName<Book>
{
}
public class ConcreteBookRepository: IBookRepository
{
public IEnumerable<Book> ListAll()
{
throw new NotImplementedException();
}
public IEnumerable<Book> ListWithTags(Expression<Func<Book, bool>> predicate)
{
throw new NotImplementedException();
}
public Book GetByName(string name)
{
throw new NotImplementedException();
}
}
In the concrete implementation you could, through composition, use a ByNameQueryer, TagQueryer and some concrete Repository.
I don't really like generic repositories, so I tend to rename IRepository to IStore since it usually only contains the CRUD aspect typically.
Oh and then some entities you can't delete, some can't be updated. You will end up breaking that down to IAdd, IUpdate, IDelete etc. This is where you start to wonder if this was actually a good idea also ;-)
I have the following classes:
// -- model hierarchy
public interface IJob {
}
public abstract class AbstractJob : IJob {
}
public class FullTimeJob : AbstractJob {
}
// -- dao hierarchy
public interface IJobDao<T> where T : IJob {
T findById(long jobId);
long insert(T job);
}
public interface IFullTimeJobDao : IJobDao<FullTimeJob> {
}
public abstract class AbstractDao {
}
public abstract class AbstractJobDaoImpl<T> : AbstractDao, IJobDao<T> where T : IJob {
public T findById(long jobId) {
// omitted for brevity
}
public long insert(T job) {
// omitted for brevity
}
}
public class FullTimeJobDaoImpl : AbstractJobDaoImpl<FullTimeJob>, IFullTimeJobDao {
}
I'm calling the following code from a factory method, which does not seem to work:
public IJobDao<IJob> createJobDao(long jobDaoTypeId)
{
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
return jobDao as IJobDao<IJob>; // <-- this returns null
return (IJobDao<IJob>) jobDao; // <-- this cast fails
}
How is this "up cast" properly achieved?
Make IJobDao interface covariant:
public interface IJobDao<out T> where T : IJob
{
T findById(long jobId);
}
Update:
You cannot have interface methods both returning and accepting generic values and make it covariant at the same time.
Possible solutions:
create a non-generic version of IJobDao<T> - IJobDao (of course, you'll have to implement both interfaces in classes, implementing IJobDao<T>)
split IJobDao<T> into 2 interfaces (one covariant and one contravariant)
consider a solution with only non-generic interface IJobDao (you are not getting any type-safety here anyway, which is the main purpose of generics)
Some ideas on implementing first scenario:
public interface IJobDao
{
IJob findById(long jobId);
long insert(IJob job);
}
public interface IJobDao<T> : IJobDao
where T : IJob
{
new T findById(long jobId);
new long insert(T job);
}
public abstract class JobDaoBase<T> : IJobDao<T>, IJobDao
where T : IJob
{
public abstract T findById(long jobId);
public abstract long insert(T job);
IJob IJobDao.findById(long jobId)
{
return findById(jobId);
}
long IJobDao.insert(IJob job)
{
return insert((T)job);
}
}
public class FullTimeJobDaoImpl : JobDaoBase<FullTimeJob>
{
public override FullTimeJob findById(long jobId)
{
// implementation
}
public override long insert(FullTimeJob job)
{
// implementation
}
}
// we are still unable to return generic interface, but we don't need to.
public static IJobDao createJobDao(/* my params */)
{
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
return jobDao as IJobDao;
}
For this cast to be possible you'll need to mark the interface type parameter as out:
public interface IJobDao<out T> where T : IJob {...}
Then
object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
var r = jobDao as IJobDao<IJob>; //not null
But this brings some restrictions on the interface. Read out (Generic Modifier) (C# Reference) for more info.
In a generic interface, a type parameter can be declared covariant if
it satisfies the following conditions:
The type parameter is used only as a return type of interface methods and not used as a type of method arguments.
The type parameter is not used as a generic constraint for the interface methods.
Consider using Inversion of Control approach with a container. The various implementations register themselves in the container. The resolver enquires please an instance of (x).
See Unity as 1 of many IOC Container tools.
public enum RepositoryType
{
ClinicRepository,
MedicationRepository,
PatientRepository,
TreatmentRepository
}
public class ObjectFactory<T>
{
public static IRepository<T> GetRepositoryInstance(RepositoryType type)
{
switch (type)
{
case RepositoryType.ClinicRepository:
return new what ?;
default:
return what ?
}
}
}
public interface IRepository<T>
{
void Add(T item);
void Remove(int id);
void Update(T item);
IList<T> GetAll();
T GetItemById(int id);
}
I'm trying to create a RepositoryFactory class and I copied what I've done so far. Could anyone please help me to figure this out ? I'm stuck !
Thanks in advance
edit :
I want something like this at the end. Is it possible to make 1 Repository class and implement something like
dc.THATOBJECT.insertonsubmit(item) ?
public class TreatmentRepository : IRepository<Treatment>
{
public void Add(Treatment item)
{
using (PatientsDataContext dc = new PatientsDataContext())
{
dc.Treatments.InsertOnSubmit(item);
dc.SubmitChanges();
}
}
The simplest of factories just requires that your types derived from IRepository have parameterless constructors.
public class ObjectFactory {
public static TRepository GetRepositoryInstance<T, TRepository>()
where TRepository : IRepository<T>, new() {
return new TRepository();
}
}
If you require specific constructors for a given repository type, you can specify the objects as an object array and create them using CreateInstance
public class ObjectFactory {
public static TRepository GetRepositoryInstance<T, TRepository>(
params object[] args)
where TRepository : IRepository<T> {
return (TRepository)Activator.CreateInstance(typeof(TRepository), args);
}
}
To use either of these, you just need to say
var treatmentRepo =
ObjectFactory.GetRepositoryInstance<Treatment, TreatmentRepository>();
To have something to return, you need to write a class that implements IRepository<T>.
public class SomeKindOfRepository<T> : IRepository<T>
{
public void Add(T item)
{
}
// and so on...
}
It appears there are four broad types (ClinicRepository, MedicationRepository, etc.) - are they very different in how they "store" things? If so, make a separate class for each one. Otherwise use the same class with some fields to control its behaviour.
Update
Based on your edits and comments, you have a repository that is really some operations on a table. The only thing that really varies is which table it wraps around. But the table is a member of a data context. So you could defer the choice of table to a derived class.
This would be the base class:
public class GeneralRepository<TEntity, TContext> : IRepository<TEntity>
{
protected abstract Table<TEntity> GetTable(TContext dc);
public void Add(Treatment item)
{
using (TContext dc = new TContext())
{
GetTable(dc).InsertOnSubmit(item);
dc.SubmitChanges();
}
}
// and so on for other methods
}
A derived class would only have to specify how to select a table from the context:
public class TreatmentsRepository : GeneralRepository<Treatment, PatientsDataContext>
{
protected override Table<Treatment> GetTable(PatientsDataContext dc)
{
return dc.Treatments;
}
}
You can do without the enum. You either need a generic repository type, or different repository types implementing IRepository<T>. If you use a generic repository, you can implement the factory by doing something along the lines of:
public class ObjectFactory<T>
{
public static IRepository<T> GetRepositoryInstance()
{
return new Repository<T>();
}
}
I would recommend that you use an Inversion of Control (IoC) container for this. In the Factory (or you could even go straight to the IoC container), could get the type.
public interface IClinicRepository : IRepository<Clinic> {}
public class ObjectFactory
{
public static IRepository<T> GetRepository(RepositoryType type)
{
switch (type)
{
case RepositoryType.ClinicRepository:
return container.Resolve<IClinicRepository>()
default:
throw new NotSupportedException()
}
}
}
or better yet Just use a generic method in your factory
public static IRepository<T> GetRepository<T>()
{
return container.Resolve<T>()
}
// to call it
var repository = ObjectFactory.GetRepository<IClinicRepository>();