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

发布于 2024-11-03 20:27:47 字数 1580 浏览 4 评论 0 原文

我有两种 POCO 类型,A 和 B。我为每种类型都有一个存储库,Rep>和 Rep>,两者都实现了 IRep>和 IRep>由 IoC 容器(本例中为 AutoFac)提供服务。

存储库有多种类型 - 从数据库(或其他)按需加载、延迟加载的内存集合、缓存的 Web 服务结果等。调用者无法分辨出区别。两个代表>和代表>恰好是内存中的集合,因为 A 和 B 变化不大并且存在很长时间。

B 的属性之一是 A。我现在要做的是,当向 B 询问其 A 时,B 会得到 IRep> 。找到它的 A 并返回它。它每次都会这样做 - 对 B 的 A 的每个请求都涉及 IRep>.Find()。好处是 B 永远不会保留 A 的,并且每个请求都会考虑 Rep 的状态。缺点是需要大量 IoC/IRep> 操作。搅动。

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

我正在为 Rep> 寻找一种干净的方法当它发生变化时通知任何感兴趣的人。在我的例子中,某个B的A可能会被删除,所以我想Rep>当删除或添加某些内容等时引发事件。Rep>可能会订阅此事件来清理任何引用现在已消失的 A 的 B,等等。如何连接它?

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

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

从本质上讲,当 Rep> 时,被实例化后,它希望将自己注册到 Rep> 中;用于事件通知。我不想污染 IRep>接口,因为这对于存储库层之外的任何人来说都不重要。而其他类型的存储库可能根本不必担心这一点。

这有什么意义吗?

I have two POCO types, A and B. I have a repository for each, Rep<A> and Rep<B>, both of which implement IRep<A> and IRep<B> served up by an IoC container (AutoFac in this case).

There are several kinds of repositories - load-on-demand from a DB (or whatever), lazy-loaded in-memory collections, cached web-service results, etc. Callers can't tell the difference. Both Rep<A> and Rep<B> happen to be in-memory collections as A's and B's don't change very much and live a long time.

One of the properties of B is an A. What I do now is, when a B is asked for its A, B gets IRep<A> to find its A and returns it. It does this every time - every request for B's A involves IRep<A>.Find(). The upside is B's never hold onto A's and each request takes into account whatever the state of Rep happens to be. The downside is a lot of IoC/IRep<A> churn.

I am thinking of using the Lazy<T> pattern here so that a B asks IRep<A> once and holds onto what it got. But what happens if an A is deleted from its repository?

I am looking for a clean way for Rep<A> to notify whoever is interested when it has changed. In my example, a certain B's A may be deleted, so I would like Rep<A> to raise an event when something is deleted, or added, etc. Rep<B> might subscribe to this event to clean up any B's that refer to A's that are now gone, etc. How to wire it up?

Ideally nothing changes when instantiating a Rep<A>. It should have no idea who listens, and A's might be manipulated all day long without ever firing up a Rep.

But when Rep<B> is born it needs a way to subscribe to Rep<A>'s event. There might not be a Rep<A> alive yet, but surely there will be once a B is asked for its A, so it seems ok to fire up a Rep<A>.

In essense, when Rep<B> is instantiated, it want it to register itself with Rep<A> for the event notification. I don't want to pollute the IRep<T> interface becaue this shouldn't matter to anyone outside the Repository layer. And other types of repositories might not have to worry about this at all.

Does this make any sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

才能让你更想念 2024-11-10 20:27:47

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

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

What if you made the Rep<A> return an "observable" object that can evaluate to an A, and also has a subscribable event that is raised when something about that A changes? Just a thought. This way, you don't have to have the handlers check to make sure that their A changed; if the event they're listening for is fired, it concerns their instance and not any other.

You might code it as follows:

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;

Now, the consuming code will be notified if the internal reference is changed, or the observable is disposed (which also disposes of the internal reference). To have the observable also notify consuming code if child references of As change, A must itself be observable, firing an event handled by Observable<T> which will "bubble" it through either ReferenceChanged or a more specific handler such as InstanceDataChanged,(or whatever you want to call it).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文