最佳实践通常是主观的,并且可能会引起与解决同样多的问题。什么时候应该继承?什么时候应该组合?学者们花费多年时间就问题的细节进行争论。具有简单接口的基本继承是实用和有效的。如果对于所有您的实体来说这是一个标准功能,则继承可能是更好的选择。
我有一个包含审计属性并实现了这些属性接口的基类。 我使用以下代码拦截调用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行代码 - 实用、简单和有效。从您的问题中可以听出您完全反对继承,这往往会带来许多困难。我也是,但我仍然坚称在这种情况下它是更好的选择。