AutoFac IoC,DDD和存储库间依赖关系

n8w*_*wrl 5 domain-driven-design repository inversion-of-control autofac

我有两个POCO类型,A和B.我有一个存储库,每个,Rep <A>和Rep <B>,它们都实现了由IoC容器(在这种情况下为AutoFac)提供的IRep <A>和IRep <B>.

有几种存储库 - 来自数据库(或其他)的按需加载,延迟加载的内存中集合,缓存的Web服务结果等.调用者无法区分.Rep <A>和Rep <B>碰巧都是内存中的集合,因为A和B的变化不大并且活很长时间.

B的一个属性是A.我现在做的是,当B要求它的A时,B得到IRep <A>找到它的A并返回它.它每次都这样做 - 每次请求B的A都涉及IRep <A> .Find().好处是B从不持有A,每个请求都考虑到Rep的状态.缺点是很多IoC/IRep <A>流失.

我正在考虑在<T这里使用Lazy >模式,这样B就会询问IRep <A>一次并保持它所得到的.但是如果A从其存储库中删除会发生什么?

我正在为Rep <A> 寻找一个干净的方式来通知任何感兴趣的人.在我的例子中,可能会删除某个B的A,所以我希望Rep <A>在删除或添加某些内容时引发事件等.Rep <B>可能会订阅此事件以清除任何引用A的B.现在已经消失,等等如何连线?

理想情况下,实例化Rep <A> 时没有任何变化.它应该不知道谁在听,A可能会整天被操纵而不会激活一个Rep.

但是当Rep <B>诞生时,它需要一种方式来订阅Rep <A>的事件.可能还没有Rep <A> alive,但肯定会有一个B被要求它的A,所以似乎可以启动一个Rep <A>.

在本质上,当Rep <B>被实例化时,它希望它使用Rep <A>为事件通知注册自己.我不想污染IRep <T>接口,因为这对于Repository层之外的任何人都无关紧要.其他类型的存储库可能根本不用担心这个问题.

这有意义吗?

Kei*_*thS 3

如果您返回Rep<A>一个“可观察”对象,该对象可以计算为 A,并且还有一个可订阅事件,当 A 的某些内容发生变化时会引发该事件,该怎么办?只是一个想法。这样,您就不必让处理程序检查以确保A 已更改;如果他们正在侦听的事件被触发,则它涉及他们的实例而不是任何其他实例。

您可以将其编码如下:

public class Observable<T>:IDisposable
{
   private T instance;
   public T Instance
   {
      get{return instance;}
      set{
         instance = value;
         var handlers = ReferenceChanged;
         if(handlers != null) handlers(this, instance);
   }

   public static implicit operator T(Observable<T> obs)
   {
      return obs.Instance;
    }

   //DO NOT attach anonymous delegates or lambdas to this event, or you'll cause a leak
   public event EventHandler<T> ReferenceChanged;

   public void Dispose()
   {
      var handlers = ReferenceChanged;
      if(handlers != null) handlers(this, null);
      foreach(var handler in handlers) ReferenceChanged -= handler;
   }
}

public class Rep<T>
{
   private Dictionary<T, Observable<T>> observableDictionary = new Dictionary<T, Observable<T>>();

   ...
   public Observable<T> GetObservableFactory(Predicate<T> criteria)
   {
      //criteria should test only uniquely-identifying information
      if(observableDictionary.Keys.Any(criteria))
         return observableDictionary[observableDictionary.Keys.First(criteria)];
      else
      {
         //TODO: get object from source according to criteria and set to variable queryResult
         var observable = new Observable<T>{Instance = queryResult};
         observableDictionary.Add(queryResult, observable);
         return observable;
      }
   }
}

...

var observableA = myRepA.GetObservable(myCriteria);
observableA.ReferenceChanged += DoSomethingWhenReferenceChanges;
Run Code Online (Sandbox Code Playgroud)

现在,如果内部引用发生更改,或者可观察对象被处置(也处置了内部引用),则使用代码将收到通知。为了让可观察对象在 As 的子引用发生变化时也通知消费代码,A 本身必须是可观察的,触发一个由其处理的事件,该事件Observable<T>将通过 ReferenceChanged 或更具体的处理程序(例如 InstanceDataChanged)“冒泡”它,(或任何您想要的处理程序)叫它)。