今天介绍一下我参与的项目中用到的系统框架结构。这里先来一张系统框架图。
1、典型的三层结构,主体包含了表示层(USL)、业务逻辑层(BLL)、数据访问层(DAL)。猛然看上去好像与别的三层结构没什么不同,不过这里的不同之处是业务逻辑层和数据访问层是以接口的形式提供的,也就是说这样的业务逻辑和数据访问均可能有不同的实现。这一点对于不同的服务调用、不同的数据来源、不同的表现逻辑是很具有灵活性的。
2、 IOC容器粘合了接口组件和实现接口的不同实现模块,使它们成为一个内聚的应用程序。接口的不同实现通过配置文件在运行时进行了运态的匹配,这样保证了框架有足够的灵活性来应对可能发生的变化和不同的场景。
3、对WCF的支持。通过分离Contract、Service和Host提供清晰的逻辑结构和便捷的WCF调用,当然WCF的数据来源或者操作也是严格遵从对IBLL的调用,调用的实际匹配也是通过IOC来配置的。
4、应用数据缓存层。在IDAL层可以看到数据层接口的实现有直接访问数据库的SqlDataProvder以及应用缓存的 CacheDataProvider实现,把它定位到IDAL层是为使缓存的使用和清除集中起来以便于跟踪、管理和排错,特别像个人空间这样具有大量缓存类型的情况来说,这样做就很有必要。在缓存排错过程中通过动态指定不同的数据来源能有效的提高排错的效率。
5、隔离所有的对外服务访问。在IBLL层我们看到有一个专门的Extensions组件(实际上可以有任意多个)来处理对外服务的访问,例如:BlogService、MessageService、MiniBlogService、NotifyService、 PassportService、ProfileService、ResService、WebIMService、CmsService等,每一种服务都对应一个服务接口,比如:IProfileService,针对这个接口都会有ProfileServiceStrategy、 ProfileServiceInvokeService、ProfileServiceInnerBuild的不同实现来对应于这个服务的“调用策略 ”、“实际服务调用”、“内部实现(或测试)”,具体在使用中使用哪种的实现来调用服务就取决于配置文件或者运行时来指定。因为这些服务都有调用异常或者调用超时的问题,这样的机制可以有效的选择调用策略,并且在调用的容错和排错、开发的调试和测试都十分有用。当然这其中的粘合剂也是IOC容器。
不难看出,这样的结构体现了“接口+实现+IOC”的应用,其实WCF的应用"Contract+Service+配置(Host/Client)"也与之类拟,调用服务的客户端可以通过配置或者运行时选择不同的契约实现,当然这里也可能是同一实现的不同通道。
具体是怎样应用IOC容器呢?IOC的注入有很多形式,使用方式也很灵活,如果不控制对它的使用,就会使得整个项目都充斥着对第三方组件的引用,并且如果要替换不同的容器也变得十分困难,所以这里就需要进行必要的封装,并提供一个默认实现的应用。这样调用核心ObjectFactory就出来了,任何对接口的调用都通过这个类来获取,例如:
- public void Test()
- {
- IDataProvider provider = ObjectFactory.CreateIDataProvider();
- provider = ObjectFactory.CreateIDataProvider("CacheDataProvider");
- provider = ObjectFactory.Create<IDataProvider>("CacheDataProvider");
- }
通过这样的封装,对IOC容器的使用就被抽象出来,大多数的使用者也不需要了解它的工作细节。我具体看一下ObjectFactory是怎么写的
- public class ObjectFactory
- {
- private static IContainerDefaultImplement defaultImplement = null;
- static ObjectFactory()
- {
- if (defaultImplement == null)
- defaultImplement =ObjectFactory.Create<IContainerDefaultImplement>("ContainerDefaultImplement");
- }
- public static TInterface Create<TInterface>(Type type)
- {
- return Create<TInterface>(type.Name);
- }
- public static TInterface Create<TInterface>(string name)
- {
- return (TInterface)ContainerBuilder.Create()[name];
- }
- public static IDataProvider CreateIDataProvider()
- {
- return ObjectFactory.Create<I