我使用Repository模式设计了一些应用程序。我有一个通用的存储库:
public interface IGenericRepository<T> where T : class { // ... }
public class GenericRepository <T> : IGenericRepository<T> where T : class {// ... }
例如,我有两个实体:Order和OrderLine。 对于实体&#34; Order&#34;我只需要通用的存储库方法,所以没关系。 但对于实体&#34; OrderLine&#34;我需要一些通用的存储库方法和一些附加功能。因此,我创建了一个自定义存储库,它扩展了泛型:
public interface IOrderLinesRepository : IGenericRepository<OrderLine> {...}
public class OrderLinesRepository : GenericRepository<OrderLine>, IOrderLinesRepository
{
//... this is my additional methods here
}
但现在我想创建方法,它将按实体类型返回存储库。 如果实体具有自定义存储库 - 应该重新调整它。如果没有,方法必须返回GenericRepository。以下是我尝试创建此内容。
public sealed class RepositoryFactory
{
// Here is custom repository types
private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
{
return new Dictionary<Type, Func<DbContext, object>>
{
{ typeof(OrderLine), dbContext =>
new OrderLinesRepository(dbContext) },
};
}
// Custom repository types
private IDictionary<Type, Type> GetRepositoryTypes()
{
return new Dictionary<Type, Type>
{
{ typeof(OrderLine), typeof(IOrderLinesRepository) }
};
}
private Func<GoodWillDbContext, object> GetDefaultFactory<T>()
where T : class
{
return dbContext => new GenericRepository<T>(dbContext);
}
private Func<DbContext, object> GetFactory<T>() where T : class
{
Func<DbContext, object> factory;
var factories = GetCustomFactories();
factories.TryGetValue(typeof(T), out factory);
return factory ?? (factory = GetDefaultFactory<T>());
}
public Type GetRepoType(Type type)
{
var types = GetRepositoryTypes();
Type repoType;
types.TryGetValue(type, out repoType);
return repoType;
}
public object MakeRepository<U>(DbContext dbContext) where U : class
{
// Get repository type
// If custom type not found, it should be standart type
// IGenericRepository<U>
var type = _repositoryFactory.GetRepoType(typeof(U)) ??
typeof(IGenericRepository<U>);
var f = _repositoryFactory.GetFactory<U>();
var repo = f(dbContext);
return repo;
}
}
但由于某种原因,它无法正常工作。我有一些问题: 1. MakeRepository应该有什么类型的返回值? 2.我应该如何转换var repo = f(dbContext);到存储库类型?
或许还有另一种方法可以做我需要的事情?
答案 0 :(得分:0)
对于应该简单的事情,你的代码看起来真的很复杂......下面的例子只是虚拟代码,随时可以根据你的需要进行调整。
public static class RepositoryFactory
{
public static IGenericRepository<T> MakeRepository<T>(DbContext context)
where T : class
{
var type = typeof(T);
if (type == typeof(Car))
{
return CarRepositoryFactory.CreateCarRpository(context);
}
else if (type == typeof(Boat))
{
return BoatRepositoryFactory.CreateBoatRepository(context);
}
}
}
如何使用它:
var myRepo = (CarRepository)RepositoryFactory.MakeRepository(new MyContext());
这些代码并不是经常被修改的(你不会在每次提交时都添加一个存储库,对吗?;)),所以请自己帮忙并保持简单。 :)
编辑:如果您真的想保留您的代码,请在我的回复中添加评论,我希望我能做到。 :)
答案 1 :(得分:0)
因此,如果我理解正确,您希望能够通过实体类型获取存储库类型。我稍微修改了你的实现,我认为它应该可以工作。
public sealed class RepositoryFactory
{
public static RepositoryFactory Instance = new RepositoryFactory();
// Here is custom repository types
private IDictionary<Type, Func<DbContext, object>> GetCustomFactories()
{
return new Dictionary<Type, Func<DbContext, object>>
{
// { typeof(IOrderLinesRepository), dbContext => new OrderLinesRepository(dbContext) },
};
}
// Custom repository types
private IDictionary<Type, Type> GetRepositoryTypes()
{
return new Dictionary<Type, Type>
{
{ typeof(OrderLine), typeof(IOrderLinesRepository) }
};
}
private Func<DbContext, object> GetDefaultFactory<T>()
where T : class
{
return dbContext => new GenericRepository<T>(dbContext);
}
private Func<DbContext, object> GetFactory(Type factoryType)
{
if (factoryType == null) return null;
Func<DbContext, object> factory;
var factories = GetCustomFactories();
factories.TryGetValue(factoryType, out factory);
return factory;
}
public Type GetRepoType(Type type)
{
var types = GetRepositoryTypes();
Type repoType;
types.TryGetValue(type, out repoType);
return repoType;
}
public IGenericRepository<TEntity> MakeRepositoryByEntity<TEntity>(DbContext dbContext) where TEntity : class
{
var type = this.GetRepoType(typeof(TEntity));
var f = this.GetFactory(type) ?? GetDefaultFactory<TEntity>();
var repo = f(dbContext);
return (IGenericRepository<TEntity>)repo;
}
public TRepo MakeRepository<TRepo, TEntity>(DbContext dbContext)
where TRepo : class, IGenericRepository<TEntity>
where TEntity : class
{
var repo = this.MakeRepositoryByEntity<TEntity>(dbContext);
try
{
return (TRepo)repo;
}
catch (InvalidCastException)
{
throw new Exception($"Registered repository for entity ${typeof(TEntity).FullName} does not implement {typeof(TRepo).FullName}");
}
}
}
您可以通过以下两种方式之一调用它:
var d = RepositoryFactory.Instance.MakeRepositoryByEntity<OrderLine>(dbContext);
var d2 = RepositoryFactory.Instance.MakeRepository<IOrderLinesRepository, OrderLine>(dbContext);