我正在使用存储库模式处理C#MVC应用程序。我使用Unity作为我的IoC,以便在MVC应用程序中实现我的存储库。
我创建了以下泛型类型,目的是最大限度地减少整个应用程序中的代码复制。这是一个示例:
public abstract class GenericRepository<T, C> : IDisposable,IGenericRepository<T> where T : class where C : DbContext, new()
public async void AddObjectAsync<T>(T entity) where T : class
{
try
{
// Validate that that there is not an existing object in the database.
var x = _context.Entry(entity);
if (!Exists(entity))
{
_context.Set<T>().Add(entity); // Add the entry if it does not exist.
_context.SaveChanges();
}
else
{
UpdateObjectAsync(entity); // Update the entry if it did exist.
}
}
catch
{
throw;
}
当我使用TPC或TPH策略时这很有效,但是它不适合TPT策略。一个例子:
public abstract class Component
{
[Key]
public Guid ComponentId { get; set; }
public string Manufacturer { get; set; }
}
public class SpecialComponent : Component
{
public string ExtraSpecialProperty { get; set; }
}
我在ComponentRepository中的实现:
public class ComponentRepository : GenericRepository<Component, HappyDbContext>, IComponentRepository
{
public async void AddComponentAsync<T>(T component) where T : class
{
try
{
if(component != null)
{
AddObjectAsync(component);
}
else
{
throw new ArgumentNullException();
}
}
catch (ArgumentNullException ex)
{
_logger.WriteErrorLogAsync(ex);
throw ex;
}
}
此代码块的第一行是我遇到的问题。为了初始化GenericRepository类型,我需要为T插入一个类。在这种情况下,DbContext C将始终相同,因此无关紧要。
如何实现可与继承类型一起使用的完全通用模式?如果它是少量的项目,那么我就不那么担心了,但在这种情况下并非如此。我认为有一个更好的方法可以解决这个问题,因此我将全力以赴为您提供意见。
答案 0 :(得分:0)
看起来你可能有一个“过度泛化”的情况。
如果在{2}中进行硬编码,那么DbContext
通用似乎是浪费时间。即GenericRepository<Component, HappyDbContext>
和where C : DbContext, new()
。强类型字段_context
并使用强类型仓库中的Unity注入HappyDbContext
可能更有意义。
同样将通用实体类型向下移动到方法级别而不是类也可以简化事情:
public interface IGenericRepository
{
void AddObjectAsync<T>(T entity) where T : class;
}
public class GenericRepository : IGenericRepository
{
private readonly DbContext _context;
public GenericRepository(DbContext context)
{
_context = context;
}
....
public async void AddObjectAsync<T>(T entity) where T : class
{
// Validate that that there is not an existing object in the database.
var x = _context.Entry(entity);
if (!Exists(entity))
{
_context.Set<T>().Add(entity); // Add the entry if it does not exist.
_context.SaveChanges();
}
else
{
UpdateObjectAsync(entity); // Update the entry if it did exist.
}
}
}
public interface IComponentRepository
{
void AddComponentAsync(Component component);
// or void AddComponentAsync<T>(T component);
// depends if you'll be reusing the ComponentRepository
// for types that inherit Component but still have individual tables...
// It was a little difficult to tell from your example.
}
public class ComponentRepository : GenericRepository, IComponentRepository
{
public ComponentRepository(DbContext context) : base(context) { }
...
public async void AddComponentAsync(Component component)
{
try
{
if (component == null) throw new ArgumentNullException();
AddObjectAsync(component);
}
catch (ArgumentNullException ex)
{
_logger.WriteErrorLogAsync(ex);
throw ex;
}
}
}
希望这会有所帮助