1.缘起:
ESBasic中许多管理对象的容器都用到了这个ESBasic.ObjectManagement.IObjectRetriever接口,所以单独将其提出来介绍一下。
当我们向对象容器(Container)请求某个对象时,也许目标对象还未加载到容器中,这可能是因为容器在初始化的时候就没有加载这个对象,也有可能是因为这个对象是容器初始化以后新增到数据库(当然也有可能是其它的持久化存储)的。在这种情况下,对象容器就可以借助IObjectRetriever来将目标对象从数据库等持久化存储中加载到容器中来。
通过IObjectRetriever接口,我们就将对象的加载与对象的管理两种不同的职能区分开来了。对象的加载往往是与具体的应用密切相关的,而对象的管理功能却可以被大规模复用。不同的应用只要实现IObjectRetriever接口,然后将其注入到要复用的对象容器中,就可以使用ESBasic提供的那些有用的对象管理容器了。
对象获取器与其它组件协作时的形象示意图如下:
2.适用场合:
在实现IObjectRetriever接口或使用与之相关的对象管理容器时,必须满足一个条件:每个对象都有唯一的一个ID。
3.设计思想与实现
IObjectRetriever的接口定义如下:
{
/// <summary>
/// Retrieve 根据ID获取目标对象。
/// </summary>
TVal Retrieve(Tkey id);
/// <summary>
/// RetrieveAll 获取所有的对象。
/// </summary>
IDictionary < Tkey, TVal > RetrieveAll();
}
这个接口相当简单,其有两个泛型参数,TKey表示的是对象ID的类型,TVal就是对象自身的类型。而其中的两个方法,一个是根据ID从持久化存储中提取对象,一个则是提取所有的对象。
4. 使用时的注意事项
在实现IObjectRetriever接口时,可以有些灵活性:
(1)我们不是只能从数据库获取对象,也可以从文件获取,甚至是可以从网络获取,或者从其它的服务器获取,等等。
(2)实现RetrieveAll方法时,不一定真的要获取所有的对象。通常,RetrieveAll方法在容器初始化时使用,这时根据你应用的需求,只需要加载初始化时够用的对象就好了,因为有些对象可能在系统运行的整个生命周期内都用不上,那就没有必要加载它。甚至,你可以返回一个不包含任何元素的字典--如果容器在初始化时,不需要加载任何对象的话。
另外,还有一个你需要考虑的是对象的数量,如果对象的数量巨大,而且全部都需要在初始化时加载到容器中,则可能导致初始化要很长的时间,而且也要占用很大的内存。所以,只加载那些真正需要用到的对象,即可加快初始化速度,也可以节省内存。
5.扩展
在设计和实现多叉树(ESBasic.ObjectManagement.Trees.Multiple.IMultiTree)时,我借助了IAgileNodePicker来提取多叉树中还未加载的节点。IAgileNodePicker继承自IObjectRetriever,并添加了一个获取多叉树根节点的PickupRoot方法。
在介绍多叉树的章节,我们会再详细介绍IAgileNodePicker这个接口。