目录
备注什么是DCI?如何将Role注入到Data中?开发期注入字节码增强MixinTraitTemplateT4 + 部分类 + 显式接口实现 + 扩展类型,C#专用运行期注入Mixin动态代理为什么要用DCI?DCI在C#种的两种实现第一种:显式接口实现 + 部分类第二种实现:组合备注
备注返回目录
之前把DCI的Role和四色原型的Role给弄混了,本文也不会比较这两种Role的区别(后面有机会再说),这里简单的记录一下对DCI的理解。
参考文章:http://www.cnblogs.com/happyframework/p/3302238.html。
什么是DCI?返回目录
Context 选择 Data,让 Data 扮演 Role 执行 Interaction。
Data
用户模型(只包含数据和本地方法)。
如:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DCIStudy.V7 8 { 9 public partial class People 10 { 11 public string Name { get; set; } 12 13 public TRole Act<TRole>() 14 where TRole : class 15 { 16 return this as TRole; 17 } 18 } 19 }
Context
面向用例设设计,职责为:选择对象,让对象扮演角色,让角色执行交互。
如:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DCIStudy.V7.Company 8 { 9 public class CompanyContext 10 { 11 public void Execute() 12 { 13 //选择对象。 14 var steven = new People { Name = "Steven" }; 15 16 //扮演角色。 17 var developer = steven.Act<IDeveloper>(); 18 19 //执行交互。 20 developer.Coding(); 21 } 22 } 23 }
Interaction
角色的行为驱动用例的执行。
如:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using DCIStudy.V7.Company; 8 9 namespace DCIStudy.V7 10 { 11 public partial class People : IDeveloper 12 { 13 void IDeveloper.Coding() 14 { 15 Console.WriteLine(string.Format("{0},快乐的编程中!",this.Name)); 16 } 17 } 18 }
如何将Role注入到Data中?返回目录
开发期注入返回目录
字节码增强返回目录
下文的语法是AspectJ吗?我没有验证,有懂的朋友给我留言,我感觉字节码增强是可以实现的。
Mixin返回目录
http://www.cnblogs.com/happyframework/archive/2013/04/25/3040461.html。
Trait返回目录
Trait本质上是一种Mixin的实现,Scala和Php5.4在语法级别支持了trait。
http://php.net/manual/en/language.oop5.traits.php。
Template返回目录
http://www.cnblogs.com/stephen-liu74/archive/2012/08/12/2635583.html。
T4 + 部分类 + 显式接口实现 + 扩展类型,C#专用返回目录
后面会给出示例,因为T4 + 扩展类型都是为了复用的,后文只给出显示接口实现 + 部分类的代码,如果有复用需求,可以引入T4 + 扩展类型。
运行期注入返回目录
Mixin返回目录
Mixin也分开发期间Mixin和运行期间Mixin。
凡是支持OpenClass的语言都支持运行期间Mixin,如:Ruby、Python和Javascript。OpenClass的本质是运行期间可以修改类型系统,也叫“动态类型”,像Php这种静态类型语言就没有这个特性,虽然Php是弱类型和解释执行的。
http://www.cnblogs.com/happyframework/archive/2013/04/25/3040461.html(重点看Ruby)。
动态代理返回目录
http://www.cnblogs.com/happyframework/p/3295853.html
为什么要用DCI?返回目录
如果将DCI作为一种编程模式或设计模式的话,我是比较认可的,作为一种架构模式,还有待考量,等有机会用一下再做评价。
DCI在C#种的两种实现返回目录
第一种:显式接口实现 + 部分类返回目录
项目结构
代码(给出一个上下文的代码)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DCIStudy.V7.Home 8 { 9 public class HomeContext 10 { 11 public void Execute() 12 { 13 //选择对象。 14 var steven = new People { Name = "Steven" }; 15 16 //扮演角色。 17 var player = steven.Act<IPlayer>(); 18 19 //执行交互。 20 player.Play(); 21 } 22 } 23 } 24 25 using System; 26 using System.Collections.Generic; 27 using System.Linq; 28 using System.Text; 29 using System.Threading.Tasks; 30 31 namespace DCIStudy.V7.Home 32 { 33 public interface IPlayer 34 { 35 void Play(); 36 } 37 } 38 39 using System; 40 using System.Collections.Generic; 41 using System.Linq; 42 using System.Text; 43 using System.Threading.Tasks; 44 45 using DCIStudy.V7.Home; 46 47 namespace DCIStudy.V7 48 { 49 public partial class People : IPlayer 50 { 51 void IPlayer.Play() 52 { 53 Console.WriteLine(string.Format("{0},疯狂的游戏中!",this.Name)); 54 } 55 } 56 } 57 58 using System; 59 using System.Collections.Generic; 60 using System.Linq; 61 using System.Text; 62 using System.Threading.Tasks; 63 64 namespace DCIStudy.V7 65 { 66 public partial class People 67 { 68 public string Name { get; set; } 69 70 public TRole Act<TRole>() 71 where TRole : class 72 { 73 return this as TRole; 74 } 75 } 76 }
第二种实现:组合返回目录
项目结构
代码(给出一个上下文的代码)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DCIStudy.V8.Company 8 { 9 public class CompanyContext 10 { 11 public void Execute() 12 { 13 //选择对象。 14 var steven = new People { Name = "Steven" }; 15 16 //扮演角色。 17 var developer = steven.Act<Developer>(); 18 19 //执行交互。 20 developer.Coding(); 21 } 22 } 23 } 24 25 using System; 26 using System.Collections.Generic; 27 using System.Linq; 28 using System.Text; 29 using System.Threading.Tasks; 30 31 namespace DCIStudy.V8.Company 32 { 33 public class CompanyContext 34 { 35 public void Execute() 36 { 37 //选择对象。 38 var steven = new People { Name = "Steven" }; 39 40 //扮演角色。 41 var developer = steven.Act<Developer>(); 42 43 //执行交互。 44 developer.Coding(); 45 } 46 } 47 } 48 49 using System; 50 using System.Collections.Generic; 51 using System.Linq; 52 using System.Text; 53 using System.Threading.Tasks; 54 55 namespace DCIStudy.V8 56 { 57 public class People 58 { 59 public string Name { get; set; } 60 61 public TRole Act<TRole>() 62 where TRole : class 63 { 64 var role = Activator.CreateInstance<TRole>(); 65 66 (role as dynamic).People = this; 67 68 return role; 69 } 70 } 71 }
备注返回目录
相对于DDD,DCI给出的模式显得过于泛化了,如:分层、分区(BondedContext)、每个层有哪些元素、如何交互等,DCI、四色原型和DDD应该可以以某种形式融合,有待慢慢思考。