Domain driven design AutoFac IoC、DDD和存储库间依赖关系

Domain driven design AutoFac IoC、DDD和存储库间依赖关系,domain-driven-design,repository,inversion-of-control,autofac,Domain Driven Design,Repository,Inversion Of Control,Autofac,我有两种POCO类型,A和B。我分别有一个存储库Rep和Rep,这两种类型都实现了IoC容器(本例中为AutoFac)提供的IRep和IRep 有几种类型的存储库——从数据库按需加载(或其他类型),内存集合中的延迟加载,缓存的web服务结果,等等。调用方无法区分它们之间的区别。Rep和Rep碰巧都在内存集合中,因为A和B的变化不大,并且存在很长时间 B的一个属性是A。我现在做的是,当A要求B提供其A时,B获取IRep以找到其A并返回它。它每次都这样做-每个B的A请求都涉及IRep.Find()。

我有两种POCO类型,A和B。我分别有一个存储库Rep
和Rep
,这两种类型都实现了IoC容器(本例中为AutoFac)提供的IRep
和IRep

有几种类型的存储库——从数据库按需加载(或其他类型),内存集合中的延迟加载,缓存的web服务结果,等等。调用方无法区分它们之间的区别。Rep
和Rep
碰巧都在内存集合中,因为A和B的变化不大,并且存在很长时间

B的一个属性是A。我现在做的是,当A要求B提供其A时,B获取IRep
以找到其A并返回它。它每次都这样做-每个B的A请求都涉及IRep
.Find()。好的一面是B永远不会抓住A,每个请求都会考虑代表的状态。缺点是大量IoC/IRep

我正在考虑在这里使用Lazy
模式,以便a B询问IRep
一次,并保留它得到的结果。但是,如果从存储库中删除A,会发生什么情况

我正在寻找一种干净的方式,让Rep
在它发生变化时通知感兴趣的人。在我的示例中,某个B的a可能会被删除,因此我希望Rep
在删除或添加某个内容时引发一个事件,等等。Rep
可能会订阅此事件,以清理任何引用a的B,这些B现在已经消失,等等。如何连接它

理想情况下,实例化Rep
时不会发生任何更改。它应该不知道谁在听,而且A可能会被操纵一整天,而不会引起代表的注意

但是当Rep
诞生时,它需要一种订阅Rep
事件的方式。可能还没有一个Rep
处于活动状态,但肯定会有一次a B被请求它的a,因此启动Rep
似乎是可以的

在本质上,当Rep
被实例化时,它希望它向Rep
注册自己以获得事件通知。我不想污染IRep
接口,因为这对存储库层之外的任何人都不重要。其他类型的存储库可能根本不必担心这一点


这有意义吗?

如果让
Rep
返回一个“可观察”的对象,该对象可以计算为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;
可观察的公共类:IDisposable
{
私人T实例;
公共T实例
{
获取{return instance;}
设置{
实例=值;
var handlers=ReferenceChanged;
if(handlers!=null)handlers(this,instance);
}
公共静态隐式算子T(可观测obs)
{
返回obs.Instance;
}
//不要将匿名委托或lambda附加到此事件,否则将导致泄漏
公共事件事件处理程序引用已更改;
公共空间处置()
{
var handlers=ReferenceChanged;
if(handlers!=null)handlers(this,null);
foreach(处理程序中的变量处理程序)ReferenceChanged-=处理程序;
}
}
公开课代表
{
私有字典observedictionary=新字典();
...
公共可观察GetObservableFactory(谓词条件)
{
//标准应仅测试唯一标识信息
if(可观察的指令键任何(标准))
返回ObservateDictionary[ObservateDictionary.Keys.First(条件)];
其他的
{
//TODO:根据条件从源获取对象并设置为变量queryResult
var observable=new observable{Instance=queryResult};
添加(查询结果,可观察);
可观测收益;
}
}
}
...
var Observable a=myRepA.GetObservable(myCriteria);
observableA.ReferenceChanged+=参考变化时的dosomething;

现在,如果内部引用发生更改,或可观察对象被处置(这也处置了内部引用),消费代码将被通知。要让可观察对象在子引用发生As更改时也通知消费代码,A本身必须是可观察的,并触发由
可观察的
处理的事件,该事件将“冒泡”它可以通过引用更改或更具体的处理程序(如InstanceDataChanged,或任何你想称之为InstanceDataChanged的处理程序)进行更改。

Ooh我喜欢这个!我必须做一些实验,但这是一个很好的方法。谢谢Keith!