I am working on a project that is built on .NET 4.5, EF5 and GenericRepository.EntityFramework. I am trying to create a publication service that will take some actions on records in an database used specifically for authoring and move
The first problem is that the cast of my types to (IBaseRepository<BaseEntity>)
fails.
I am successful when testing with the first repository (the one I listed in the sample DataBucket class below) by using a direct cast of...
object myRepository = p.GetValue(entity, null);
IBaseRepository<MRClassification> risk = myRepository;
because myRepository takes a 'MRClassification' object type
The problem is that each repository are not of the same signature, is it possible to return a list of IBaseRepository<p.PropertyType.GetInterfaces()[0].GenericTypeArguments[0]>
which will return me the entity that each repository takes as a type?
I thought about using covariance but I have methods in the BaseRepository that take T as a parameter like
public virtual new void Add(T entity) { do something; }
Publication App Code
public static void DeactivateNonTransversableExpiredRecords()
{
IEnumerable<Tuple<IBaseRepository<BaseEntity>, Type>> nonTransversableList =
GetNonTransversableRepositories(Databucket);
foreach (var repository in nonTransversableList)
{
////IQueryable recordsToExpire =
////((IBaseRepository<BaseEntity>)repository).FindBy(
//// p => Convert.ToDateTime(p.ExpirationDate).Date <= DateTime.Now.Date && p.IsActive);
IQueryable recordsToExpire = repository.Item1.FindBy(p => p.IsActive);
foreach (var row in recordsToExpire)
{
((BaseEntity)row).IsActive = false;
((IBaseRepository<BaseEntity>)repository).Edit((BaseEntity)row);
}
}
}
private static IEnumerable<Tuple<IBaseRepository<BaseEntity>, Type>> GetNonTransversableRepositories(object entity)
{
PropertyInfo[] properties =
entity.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
List<Tuple<IBaseRepository<BaseEntity>, Type>> list = new List<Tuple<IBaseRepository<BaseEntity>, Type>>();
foreach (PropertyInfo p in properties)
{
if (!typeof(ITransversableRepository).IsAssignableFrom(p.PropertyType))
{
if (OpenGenericIsAssignableFrom(typeof(IBaseRepository<>), p.PropertyType))
{
list.Add(
new Tuple<IBaseRepository<BaseEntity>, Type>(
(IBaseRepository<BaseEntity>)Activator.CreateInstance(p.PropertyType),
p.GetValue(entity, null)));
}
}
}
return list;
}
POCO Entities and Repositories in DataModel Solution
--- DataBucket
public class DataBucket : Audit, IDataBucket
{
private IMRClassificationRepository mrClassCodeRepository;
public IMRClassificationRepository MRClassificationRepository
{
get { return this.mrClassCodeRepository ?? (this.mrClassCodeRepository = new MRClassificationRepository(this.dataContext)); }
}
...
}
--- Repository Class Headers
public class MRClassificationRepository : BaseRepository<MRClassification>, IMRClassificationRepository
{
...
}
public interface IMRClassificationRepository : IBaseRepository<MRClassification>
{
...
}
public abstract class BaseRepository<T> : CoreRepository<T>, IBaseRepository<T> where T : BaseEntity, IBaseEntity
{
...
}
public interface IBaseRepository<T> : ICoreRepository<T> where T : BaseEntity
{
...
}
--- Entity Class Headers
public class MRClassification : RiskClassification
{
...
}
public abstract class RiskClassification : Revisionable
{
...
}
public abstract class Revisionable : BaseEntity, IRevisionableEntity
{
...
}
public class BaseEntity : IBaseEntity
{
...
}
public interface IBaseEntity : IEntity<Guid>
{
...
}