c抽象类泛型属性
本文关键字:属性 泛型 抽象类 | 更新日期: 2023-09-27 18:19:48
考虑以下代码:
public abstract class RepositoryBase<T> where T : class
{
#region Members
private MyContext dataContext;
private readonly IDbSet<T> dbset;
#endregion
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get; private set;
}
protected MyContext DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual void Delete(T entity)
{
dbset.Remove(entity);
}
我想用下面的方法替换Delete方法,因为我更喜欢在我的对象中简单地将Deleted字段设置为true,以指示它已删除,而不是真正删除它
public virtual void Delete(T entity)
{
entity.Deleted = true;
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
}
我正在使用POCO实体,并且所有实体中都存在Deleted属性。然而,在上面的代码中,实体是T类型的,并且T"不知道"它所能表示的所有对象中都有Deleted属性。解决这个问题最优雅的方法是什么?
顺便说一句,我想在我的抽象类中以类似的方式访问其他字段(DateCreated、CreatedBy、DateModified和ModifiedBy)。
UPDATE:我尝试了接口和抽象类解决方案,起初看起来不错,但后来在编译时,在这两种情况下都收到了以下错误消息:
错误11类型"MyProject.Domain.Person"不能用作泛型类型或方法"MyProject.Data.Infrastructure.RepositoryBase"中的类型参数"T"。没有从"MyProject.Domain.Person"到"MyProject''Domain.AbstractEntity"的隐式引用转换。
这是错误消息所指的代码:
namespace MyProject.Data
{
public class PersonRepository : RepositoryBase<Person>, IPersonRepository
{
public PersonRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
}
}
public interface IPersonRepository : IRepository<Person>
{
}
}
更新2:
我终于使用SLaks提出的解决方案。我使用了一个接口,并修改了生成所有POCO实体的模板,使它们都可以从以下IEntity接口派生:
namespace MyProject.Domain
{
public interface IEntity
{
System.DateTime CreatedDate
{
get;
set;
}
string CreatedBy
{
get;
set;
}
System.DateTime ModifiedDate
{
get;
set;
}
string ModifiedBy
{
get;
set;
}
bool Deleted
{
get;
set;
}
}
}
使用抽象实体类会更复杂,因为这样抽象类中的所有属性都必须在实体类中重写。
将Deleted属性放入一个接口(比如IDeletable)中,并用一个通用约束约束该类:
public interface IDeleteable { Boolean Deleted { get; set; } }
public abstract class RepositoryBase<T> where T : class, IDeleteable
编辑:我认为这是隐含的,但你需要在实体类中实现接口,例如
public class Person : IDeleteable { ... }
您应该创建一个具有Deleted
和其他属性的接口,并在实体类中实现它
然后可以约束泛型类型参数来实现接口。
您可以为约束使用抽象类
// from
public abstract class RepositoryBase<T> where T : class
// to
public abstract class RepositoryBase<T> where T : AbstractEntity
其中AbstractEntity将具有所需的所有属性。与接口相比,抽象类将允许您提供一些默认实现。
其他人提到使用接口或抽象类。这也是我全心全意推荐的。如果出于某种愚蠢的原因,这是不可能的,你也可以使用反射:
entity.Deleted = true;
将替换为:
var type = typeof(T);
var property = type.GetProperty("Deleted");
property.SetValue(entity, true, null);