有沒有好辦法做到這一點。在構造實體對象之後但在調用代碼中枚舉之前,似乎沒有簡單的方法將任何代碼注入進程。
Subclassing InternalDbSet是我考慮過的事情,但您只能修復對.Find方法和IQueryable實現(您使用DbSet的主要方式)的調用是遙不可及的。
因此,我可以看到的唯一選擇是不允許訪問DbSet,但具有訪問器函數,它將爲我設置.Owner(或任何您想調用它的)屬性。這很麻煩,因爲你通常必須爲每個你想要的查詢類型編寫一個函數,而調用者不能再使用LINQ。但我們可以使用泛型和回調來保留大部分的靈活性,儘管它看起來很醜。這是我想出來的。
我正在移植和清理一個複雜的系統,所以我不能真正測試這個,但這個概念是完善的。代碼可能需要進一步調整才能按需要工作。在處理任何記錄之前,只要您使用EnumerateEntities枚舉而不是QueryEntities,但是我還沒有對此進行任何實際測試,這應該不會有任何處罰。
private void InitEntity(Entity entity) {
if (entity == null) {
return;
}
entity.Owner = this;
// Anything you want to happen goes here!
}
private DbSet<Entity> Entities { get; set; }
public IEnumerable<Entity> EnumerateEntities() {
foreach (Entity entity in this.Entities) {
this.InitEntity(entity);
yield return entity;
}
}
public IEnumerable<Entity> EnumerateEntities(Func<DbSet<Entity>, IEnumerable<Entity>> filter) {
IEnumerable<Entity> ret = filter(this.Entities);
foreach (Entity entity in ret) {
this.InitEntity(entity);
yield return entity;
}
}
public T QueryEntities<T>(Func<DbSet<Entity>, T> filter) {
if (filter is Func<DbSet<Entity>, Entity>) {
T ret = filter(this.Entities);
this.InitEntity(ret as Entity);
return ret;
}
if (filter is Func<DbSet<Entity>, IEnumerable<Entity>>) {
IEnumerable<Entity> ret = filter(this.Entities) as IEnumerable<Entity>;
// You should be using EnumerateEntities, this will prefetch all results!!! Can't be avoided, we can't mix yield and no yield in the same function.
return (T)ret.Select(x => {
this.InitEntity(x);
return x;
});
}
return filter(this.Entities);
}
public void QueryEntities(Action<DbSet<Entity>> filter) => filter(this.Entities);
謝謝 - 這結束了我的絕望搜索 – Kathleen