让我们想象下面的情况(假设只有模型和视图/业务层,我会简化)
我正在使用Entity Framework,我希望将所有更改记录为Log表中的JSON。
我已经能够通过覆盖DbContext.SaveChanges()方法并读取ChangeTracker()来实现这一目的。
以下是一个例子:
public class LogContext : DbContext
{
public LogContext(string context)
: base(context)
{
}
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
var added = ChangeTracker.Entries().Where(x => x.State == EntityState.Added).ToList();
var modified = ChangeTracker.Entries().Where(x => x.State == EntityState.Modified).ToList();
var deleted = ChangeTracker.Entries().Where(x => x.State == EntityState.Deleted).ToList();
Logger.RecordAdded(added);
Logger.RecordModified(modified);
Logger.RecordDeleted(deleted);
}
}
我的RealContext
将要实例化此LogContext
即将调用我的Logger
。
如果我有2个项目,一个用于Model,另一个用于我的View / Business,我希望能够在Logger类中获取Logged用户,即使Model层不知道哪种View / Business正在调用它(MVC项目,Windows窗体等)。
我的想法是发送一个Func<>作为参数,此函数将使用户在View / Business层上(即使在模型上调用时),但这意味着重写所有SaveChanges调用以发送此函数。
我想知道是否有某种方式来注射"这个函数无需在整个项目中重写所有的SaveChanges。
非常感谢。
答案 0 :(得分:1)
不是将用户返回到基本记录器,而是将其暴露给它不应该真正了解的概念,为什么不实现标记或附加信息系统?扩展现有的LogContext:
public class LogContext : DbContext
{
private readonly Func<string> _getAdditionalInfoFunc;
public LogContext(string context, Func<string> getAdditionalInfoFunc)
: base(context)
{
_getAdditionalInfoFunc = getAdditionalInfoFunc;
}
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
var added = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added).ToList();
var modified = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Modified).ToList();
var deleted = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Deleted).ToList();
string extraInfo = _getAdditionalInfoFunc != null
? _getAdditionalInfoFunc()
: string.Empty;
Logger.RecordAdded(added, extraInfo);
Logger.RecordModified(modified, extraInfo);
Logger.RecordDeleted(deleted, extraInfo);
}
}
这将是一个非常灵活的解决方案。然后,您可以让注入器注入一个func,它以自由格式返回一个包含所需上下文相关信息的字符串。
根据需要它的类的位置注入不同实现的好处是,有时可能会在用户操作的上下文中调用低级代码。如果您将特定记录器提供给特定类,则可能会丢失相关的上下文信息。如果你有一个总是检查用户上下文的func,当记录器记录时,它会找到上下文存在的任何调用的上下文。