Newlife.XCode对象容器与接口操作实例

        本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html

Newlife XCode组件相关文章目录:http://www.cnblogs.com/asxinyu/p/4329747.html

1.前言

最近一个人狂看X组件的源码,从CommonEntityXCode,然后XCoderXCode。感觉自己有很大的进步,视野更加开放,也能够更加顺手的做很多事情。

大石头在5月份左右的时候,录制了几期视频教程,其中有一期“使用对象容器来解耦业务模块与管理平台”,对理解X组件很有好处,这期视频我前后已经听了4遍,当然每听一遍都有一些新的发现与体会。今天要总结也是对象容器的一点理解以及为了解决问题,在XCoder源码中发现的一些东西:接口操作。 

2.XCode对象容器介绍

 XCode对象容器的使用在XCode后台和Newlife.CommonEntity中有大量的使用,这也是后台很容易扩展的原因之一。只需要继承相应的实体类(自动注册优先级高于内部类),而基类中的代码都是通过接口操作,这样继承的类就会优先被系统采用。 管理平台和业务平台通过接口和对象容器联系起来。对象容器注册接口的优先级: 

1.对象容器注册优先采用配置文件中指定的接口 

2.配置文件里面没找到之后,会去寻找所有的程序集,找到实现该接口的类,优先级仅次于配置文件。 

3.内部实现的类优先级要低,12都没找到,就按默认的实现注册顺序采用。 

对象容器的注册在静态构造函数中,服务容器基类是泛型基类,这样只要是继承基类,然后加一个静态构造函数,就可以在程序中给实现的接口的类进行注册。 

上面是石头的一些总结,听起来可能不容易理解,下面举一个例子,也算是昨天晚上研究了2个小时的成果吧。 

3.XCoder接口操作的实例 

XCoder代码生成器中,可以将数据库模型保存为XML文件,并可以直接加载XML文件进行模型的修改操作。但是其中有一些不便利。我想做一个直接添加模型的界面,这就涉及到一个问题,如何实例化一个IDataTable对象,查看XCoder的源码发现了下面的东西: 

 1 private void btnAddTable_Click(object sender, EventArgs e)
 2         {
 3             if (Tables == null || Tables.Count < 1) return;
 4 
 5             Type type = Tables[0].GetType();
 6             if (type == null) return;
 7 
 8             IDataTable table = TypeX.CreateInstance(type) as IDataTable;
 9             if (table == null) return;
10 
11             Tables.Add(table);
12             table.ID = Tables.Count;
13             table.TableName = "NewTable" + table.ID;
14             table.Description = "新建表" + table.ID;
15 
16             SetTables(Tables, Tables.Count - 1);
17         }

 关键的代码是:Type type = Tables[0].GetType();这里直接获取当前数据库中表的类型,然后:

和 IDataTable table = TypeX.CreateInstance(type) as IDataTable; 这里实体化一个接口,再进行赋值。

XCoder内部这样做,是有优势的。因为这是导入模型之后才进行的,导入模型的时候,默认实现IDataTable的类已经确定了,因为有对象容器,看XCodeService 

 1  /// <summary>XCode服务对象提供者</summary>
 2     class XCodeService : ServiceContainer<XCodeService>
 3     {
 4         static XCodeService()
 5         {
 6             var container = Container;
 7             container.Register<IDataTable, XTable>()
 8                 .AutoRegister<IDataRowEntityAccessorProvider, DataRowEntityAccessorProvider>()
 9                 .AutoRegister<IEntityPersistence, EntityPersistence>()
10                 .AutoRegister<IModelResolver, ModelResolver>();
11 
12             DbFactory.Reg(container);
13 
14             EntityAccessorFactory.Reg(container);
15         }        
28         #region 使用
29         /// <summary>创建模型数据表</summary>    
30         public static IDataTable CreateTable()
31         {
32             return Container.Resolve<IDataTable>();
33         }
34     }

  container.Register<IDataTable, XTable>();就是XCodeService在静态构造函数中注册IDataTable的默认实现类XTable,下面的使用方法CreateTable()就是返回一个IDataTable对象,然后在系统的其他地方就可以用XCodeService的这个CreateTable方法创建IDataTable对象了。

那么为什么最上面的代码中,不这样创建IDataTable对象呢?这里代码太多了,只稍微说一下,因为第一段代码这里已经是导入模型之后了,在导入模型过程中,已经确定了Tables的类型,代码如下:

1 /// <summary>导入模型</summary>       
2         public static List<IDataTable> Import(String xml)
3         {
4             if (String.IsNullOrEmpty(xml)) return null;
5 
6             return ModelHelper.FromXml(xml, CreateTable);
7         }

这里的方法是DAL类中的,FromXML方法第二个参数是一个委托,这里传入的CreateTable就是创建默认的IDataTable实例,看看他的代码,很简单,就是内部调用一次XCodeService的方法:

1  /// <summary>建立数据表对象</summary>
2         internal static IDataTable CreateTable() { return XCodeService.CreateTable(); }

到这里应该很清楚了,XCoder中操作对表的操作,都是通过IDataTable,而不设计具体的实现类,比如XTable,在外部程序中,你可以使用自己的Table类,实现IDataTable接口,这样XCode内部会优先采用外部的实现类。

最后,说一下,这并没有解决我的问题,在这里大家可能会注意到,XCodeService类是私有的,DALCreateTable方法是internal ,这样外部程序集就没办法访问得到。如果我要在外部程序中直接获取一个IDataTable 对象,还的确办不到,除非自己重写一个IDataTable,但这样又太麻烦,既然XCode有这样的功能,不知道大石头为什么不把DALCreateTable设为Public,是不是有什么其他考虑?

posted @ 2013-01-28 09:46  数据之巅  阅读(2710)  评论(9编辑  收藏  举报