最佳实践通常是主观的,可能会导致与解决的问题一样多的问题。你应该什么时候继承?你应该什么时候作曲?学者们花费数年时间争论问题的细节。具有简单接口的基本继承是实用且有效的。如果它是所有实体的标准功能,那么继承可能是更好的选择。
我有一个带有审计属性的基类,并为这些属性实现了一个接口。context.SaveChanges()
我使用以下代码拦截对 的调用。这很简单,而且很有效。如果任何被跟踪实体未实现该IAudit
接口,它可能会扩展为失败。
public override int SaveChanges()
{
var entities = this.GetChangedAuditDataEntities();
foreach (var entity in entities)
{
this.SetModificationInfo(entity);
}
return base.SaveChanges();
}
private IEnumerable<IAuditData> GetChangedAuditDataEntities()
{
return (
from entry in _context.ChangeTracker.Entries()
where entry.State != EntityState.Unchanged
select entry.Entity)
.OfType<IAuditData>();
}
private void SetModificationInfo(IAuditData entity)
{
entity.lastModifiedBy = _currentUser.Name;
entity.lastModified = System.DateTime.Now;
}
这是不会自动获得“正确”答案的问题之一。如果 Jon Skeet 回答这个问题,那么这将被认为是最佳实践。唯一的其他正确答案将必须确认您的特定偏见,或者至少要打出正确的知识点。
多年前,继承盛行,其中的众多阻力之一就是“价值构成优于继承”的口头禅。很好,但继承有它的位置。
我建议任何具有许多相同类型对象的架构层,例如域对象(“域对象”一词暗示公共层)可以通过拥有一个公共基类来大大增强。System.Object
就是一个很好的例子。我再举一个例子。当我们为我们的解决方案定义异常装饰器时,我们决定扩展 ToString() 方法来创建一个可以唯一标识对象的值。
public override string ToString()
{
if (this is IAuditData)
{
IAuditDataidentifiable = this as IAuditData;
return string.Format(@"{0} {{ id: {1}, ETag: {2} }}",
identifiable.GetType().Name,
identifiable.id,
identifiable.ETag);
}
else return base.ToString();
}
7行代码——务实、简单、有效。从你的问题来看,你听起来完全反对继承,继承必须来自许多烧伤的手指。我也是;-) 但我仍然断言在这种情况下它是更好的选择。