本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html
Newlife XCode组件相关文章目录:http://www.cnblogs.com/asxinyu/p/4329747.html
最近一个人狂看X组件的源码,从CommonEntity到XCode,然后XCoder到XCode。感觉自己有很大的进步,视野更加开放,也能够更加顺手的做很多事情。
大石头在5月份左右的时候,录制了几期视频教程,其中有一期“使用对象容器来解耦业务模块与管理平台”,对理解X组件很有好处,这期视频我前后已经听了4遍,当然每听一遍都有一些新的发现与体会。今天要总结也是对象容器的一点理解以及为了解决问题,在XCoder源码中发现的一些东西:接口操作。
XCode对象容器的使用在XCode后台和Newlife.CommonEntity中有大量的使用,这也是后台很容易扩展的原因之一。只需要继承相应的实体类(自动注册优先级高于内部类),而基类中的代码都是通过接口操作,这样继承的类就会优先被系统采用。 管理平台和业务平台通过接口和对象容器联系起来。对象容器注册接口的优先级:
1.对象容器注册优先采用配置文件中指定的接口
2.配置文件里面没找到之后,会去寻找所有的程序集,找到实现该接口的类,优先级仅次于配置文件。
3.内部实现的类优先级要低,1,2都没找到,就按默认的实现注册顺序采用。
对象容器的注册在静态构造函数中,服务容器基类是泛型基类,这样只要是继承基类,然后加一个静态构造函数,就可以在程序中给实现的接口的类进行注册。
上面是石头的一些总结,听起来可能不容易理解,下面举一个例子,也算是昨天晚上研究了2个小时的成果吧。
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类是私有的,DAL的CreateTable方法是internal ,这样外部程序集就没办法访问得到。如果我要在外部程序中直接获取一个IDataTable 对象,还的确办不到,除非自己重写一个IDataTable,但这样又太麻烦,既然XCode有这样的功能,不知道大石头为什么不把DAL的CreateTable设为Public,是不是有什么其他考虑?