I have several IRepositories and server Repositories. I'm trying to make these repositories generic so I can use the _unitOfWork pattern. I have developed the IRepository but am having issues in the Repository as I am using DTOs. Possibly, a little code will help.
//T is an instance of T_IFS_EmployeeDTO
public T Create(T objDTO)
{
//This worked in the old specfic implementation as I just passed a T_IFS_EmployeeDTO objDTO:
T_IFS_Employee obj = _mapper.Map<T_IFS_EmployeeDTO, T_IFS_Employee>(objDTO);
//This is sort of how I see it working in the generic implementation. The baseClass method is below.
var instanceOfObjClass = baseClass();
//This is where I need to map the DTO to the instanceOfObjClass
instanceOfObjClass = _mapper.Map<T, T_IFS_Employee>(objDTO);
//In the line above, I need to pass the specific class in the place of T_IFS_Employee
//I also need to use it here...
var addedObj = _db.T_IFS_Employee.Add(obj);
_db.SaveChanges();
//and on the reverse map.
return _mapper.Map<T_IFS_Employee, T>(addedObj.Entity);
}
This is the implementation that I am attempting to make generic. I am passing the DTO so it would receive a T_IFS_EmployeeDTO obj (objDTO). To do the mapping, I need to be able to specify a T_IFS_Employee obj as well as have the class name for the DB Access. The class standards are to just add DTO to the database class. I can get the name of the class by string baseClass = typeof(T).Name; but that is only a string of the name of the class that I want. baseClass will return an instance of the class but I still need to use the class reference in the _mapper.Map call and in the _db.T_IFS_Employee.Add call. Hopefully, you can see what I am trying to do here and can provide some clarity for my actions.
Am I on the right track and just need a boost or do I have this all wrong. As always, thank you for taking the time and giving your valuable input.
The private method to create an instance:
private object baseClass()
{
string baseClass = typeof(T).Name;
baseClass = baseClass.Replace("DTO", "");
var typeOfClass = Type.GetType(baseClass);
var expressionOfClass = Expression.New(typeOfClass);
var typeFactory = Expression.Lambda<Func<dynamic>>(expressionOfClass).Compile();
return typeFactory();
}
Okay. I'm sorry but I thought I posted everything that was needed.
This is the current interface that works:
public interface IEmployeeRepository
{
public T_IFS_EmployeeDTO Create(T_IFS_EmployeeDTO objDTO);
public T_IFS_EmployeeDTO Update(T_IFS_EmployeeDTO objDTO);
public int Delete(int id);
public T_IFS_EmployeeDTO Get(int id);
public IEnumerable<T_IFS_EmployeeDTO> GetAll();
}
And this is the current implementation that works.
public class EmployeeRepository : IEmployeeRepository
{
private readonly ApplicationDbContext _db;
private readonly IMapper _mapper;
public EmployeeRepository(ApplicationDbContext db, IMapper mapper)
{
_db = db;
_mapper = mapper;
}
public T_IFS_EmployeeDTO Create(T_IFS_EmployeeDTO objDTO)
{
T_IFS_Employee obj = _mapper.Map<T_IFS_EmployeeDTO, T_IFS_Employee>(objDTO);
var addedObj = _db.T_IFS_Employee.Add(obj);
_db.SaveChanges();
return _mapper.Map<T_IFS_Employee, T_IFS_EmployeeDTO>(addedObj.Entity);
}
public int Delete(int id)
{
var obj = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == id);
if (obj != null)
{
_db.T_IFS_Employee.Remove(obj);
return _db.SaveChanges();
}
return 0;
}
public T_IFS_EmployeeDTO Get(int id)
{
var obj = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == id);
if (obj != null)
{
return _mapper.Map<T_IFS_Employee, T_IFS_EmployeeDTO>(obj);
}
return new T_IFS_EmployeeDTO();
}
public IEnumerable<T_IFS_EmployeeDTO> GetAll()
{
return _mapper.Map<IEnumerable<T_IFS_Employee>, IEnumerable<T_IFS_EmployeeDTO>>(_db.T_IFS_Employee);
}
public T_IFS_EmployeeDTO Update(T_IFS_EmployeeDTO objDTO)
{
var objFromDb = _db.T_IFS_Employee.FirstOrDefault(u => u.EmployeeID == objDTO.EmployeeID);
if (objFromDb != null)
{
_mapper.Map(objDTO, objFromDb);
_db.SaveChanges();
return _mapper.Map<T_IFS_Employee, T_IFS_EmployeeDTO>(objFromDb);
}
return objDTO;
}
}
I'm trying to implement a generic interface and generic repository because I have about 9 of these that are almost identical.
I have setup the following generic interface that seems to be correct:
public interface IRepository<T> where T : class
{
public T Create(T objDTO);
public T Update(T objDTO);
public int Delete(int id);
public T Get(int id);
public IEnumerable<T> GetAll();
T GetFirstOrDefault(Expression<Func<T, bool>>? filter = null);
}
But I'm having trouble in the implementation:
This includes some of the things I was trying to get to work so it's a little messy. I was trying to add some things to the constructor that I might be able to use in the methods. You can probably ignore that. I'm trying to get the Create method to work. As you can see in that method, I need the additional class of T_IFS_Employee. I have the T_IFS_EmployeeDTO class as the objDTO was passed. I am so sorry if this is not clear. I appreciate the time you have taken but if I knew exactly how I needed to do this, I would probably not be here. I have researched adding two classes to the interface but that does not seem to be an option.
public class Repository<T> : IRepository<T> where T : class
{
private readonly ApplicationDbContext _db;
private readonly IMapper _mapper;
internal DbSet<T> _dbSet;
private readonly Type _type;
private readonly string _typeName;
private readonly object _typeOfClass;
private readonly object _expressionOfClass;
private readonly object _typeFactory;
public Repository(ApplicationDbContext db, IMapper mapper)
{
_db = db;
_mapper = mapper;
this._dbSet = db.Set<T>();
_type = typeof(T);
_typeName = typeof(T).Name.Replace("DTO", "");
_typeOfClass = Type.GetType(_typeName);
_expressionOfClass = Expression.New(_typeOfClass);
_typeFactory = Expression.Lambda<Func<dynamic>>(_expressionOfClass).Compile();
}
public T Create(T objDTO)
{
var objClass = baseClassInstance();
T_IFS_Employee obj = _mapper.Map<T, T_IFS_Employee>(objDTO);
var addedObj = _db.T_IFS_Employee.Add(obj);
_db.SaveChanges();
return _mapper.Map<T_IFS_Employee, T>(addedObj.Entity);
}
public int Delete(int id)
{
throw new NotImplementedException();
}
public T Get(int id)
{
throw new NotImplementedException();
}
public IEnumerable<T> GetAll()
{
throw new NotImplementedException();
}
public T GetFirstOrDefault(Expression<Func<T, bool>>? filter = null)
{
throw new NotImplementedException();
}
public T Update(T objDTO)
{
throw new NotImplementedException();
}
private object baseClassInstance()
{
baseClass = baseClass.Replace("DTO", "");
var typeOfClass = Type.GetType(baseClass);
var expressionOfClass = Expression.New(typeOfClass);
var typeFactory = Expression.Lambda<Func<dynamic>>(expressionOfClass).Compile();
return typeFactory();
}
}