【问题标题】:AutoFac IoC, DDD, and inter-Repository DependenciesAutoFac IoC、DDD 和存储库间依赖关系
【发布时间】:2011-04-27 19:15:50
【问题描述】:

我有两种 POCO 类型,A 和 B。我有一个存储库,分别是 Rep<A> 和 Rep<B>,它们都实现了 IRep<A> 和 IRep<B> 服务于一个 IoC 容器(在本例中为 AutoFac)。

有几种存储库 - 从数据库(或其他)按需加载、内存中延迟加载的集合、缓存的 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> 流失。

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

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

理想情况下,实例化 Rep<A> 时不会发生任何变化。它应该不知道谁在听,而且 A 可能会整天被操纵而不会触发 Rep。

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

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

这有意义吗?

【问题讨论】:

    标签: domain-driven-design repository inversion-of-control autofac


    【解决方案1】:

    如果您让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;
    

    现在,如果内部引用被更改,或者 observable 被释放(这也释放了内部引用),消费代码将被通知。如果 As 的子引用发生变化,要让 observable 也通知消费代码,A 本身必须是可观察的,触发由 Observable&lt;T&gt; 处理的事件,这将通过 ReferenceChanged 或更具体的处理程序(例如 InstanceDataChanged)“冒泡”它,(或其他你想叫它)。

    【讨论】:

    • 哦,我喜欢这个!我必须做一些实验,但这是看待它的好方法。谢谢基思!
    猜你喜欢
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多