为了在.NET Core中使用依赖注入,我们为控制器构建了一堆存储库接口,用于数据库交互。
我们有一个EntityBase
类,其中包含一些方法,我们的通用存储库接口使用该基类,如:IRepository<T> where T : EntityBase
。
我想添加一个更具体的TaggedEntityBase
类,其扩展EntityBase
来表示我们有一些实体,我们希望按标签过滤这些实体。我希望TaggedEntityBase
有一个我可以在我的控制器中使用的抽象属性,这样我就可以抽象出来并重用过滤方法。
所以我想要的是这样的,但我想我希望ITaggedRepository
也从IRepository
继承,以便实现ITaggedRepository
的类保证ListAll
方法和ListWithTags
方法:
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);
}
我相当肯定我只是通过追求这种思路而彻底迷惑自己,但我不确定如何做我真正想要的事情。我知道我需要为依赖注入保留抽象的东西,但我觉得我正在接近界面的可能性。
有没有更好的思路可以让我到达我想去的地方?
答案 0 :(得分:2)
您可以继续并继承IRepository<T>
:
public interface ITaggedRepository<T> : IRepository<T> where T : TaggedEntityBase
{
IEnumerable<T> ListWithTags(Expression<Func<T, bool>> predicate);
}
答案 1 :(得分:2)
如果你的TaggedEntity不是真正的抽象,你可能会遇到麻烦。假设你有NamedEntities,有些是Tagged。
现在你有一个INamedRepository,ITaggedRepository和一个INamedTaggedRepository(你的基础实体会遇到类似的问题)。
你可以做类似的事情:
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();
}
}
在具体实现中,您可以通过合成使用ByNameQueryer,TagQueryer和一些具体的存储库。
我不太喜欢通用存储库,所以我倾向于将IRepository重命名为IStore,因为它通常只包含CRUD方面。
哦,然后一些实体你无法删除,有些无法更新。你最终会把它分解为IAdd,IUpdate,IDelete等。这就是你开始想知道这是否也是一个好主意; - )