Domain driven design AutoFac IoC、DDD和存储库间依赖关系
我有两种POCO类型,A和B。我分别有一个存储库RepDomain 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()。
和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!