进行项目开发的第一步,是创建出适合自己团队习惯的VS解决方案,虽然我已经提供了项目示例,但毕竟是我创建的,你直接使用可能并不合适,另外你如果尝试模仿重新创建该示例,中间可能碰到各种障碍,特别是项目间的依赖关系。

  本文的目的是帮助.Net架构初学者能顺利搭建起适合自己的VS解决方案,我会在本文演示曾经用过的几种不同风格的目录结构,你可以根据自己的习惯选择一种并自行修改。

  本系列假定你已经熟悉如何创建.NET类库等基础知识,并具有.Net开发经验,我不会详细到每一个细节。如果你是.Net初学者,尚未开发过任何实际项目,对你的建议就是关闭本页面,去买本书打好基础,需要提升时再来。

影响VS解决方案结构的因素

分层

  VS解决方案的创建,与你采用的分层方式密切相关,我在之前的文章已经简单介绍过单层架构和三层架构,本文采用DDD分层架构进行演示,说明项目示例Applications.Managements是怎样创建出来的,并且可以怎样简化。

  我们平时所说的分层,属于逻辑分层,它按照一定的逻辑层次分离关注点,以便更好的组织代码结构,方便维护。

  物理分层,是将不同的代码部署到不同的服务器,以提供更高性能和安全性,如果对逻辑分层和物理分层的关系感兴趣,请参考《C#企业应用开发艺术-CSLA.NET框架开发实战》一书。

  对于逻辑分层,只要将代码分离到不同区域即可,可以按照不同的抽象粒度来组织代码,比如类级别、目录级别、程序集级别。

  目前普遍采用的是程序集级别进行分层,即不同层的代码放到不同的程序集中。

  如果期望减少程序集,可以仅创建一个类库,采用目录级别的划分方式,在一个类库中创建不同层的文件夹,各目录放置各层的代码。

  类级别粒度将不同层的对象合并,通过方法的形式分离各层代码。

  通过程序集方式分层有诸多好处,比如清晰度、复用性等,我将采用程序集方式进行演示,建议你在项目上也尽量采用这种方式。

功能模块

  另一个影响VS解决方案创建的因素是功能模块的划分。

  对于一个业务系统,我们不仅要分层,而且还要划分功能模块,以便对较大的业务问题进行分解,从而降低复杂度,同时在解决某个特定模块的问题时,减少其它模块的干扰。

  对于领域层,我目前的方式是为每一个功能模块创建一个类库项目,这样做的好处是更方便复用,另外当我需要将这个功能模块分离出去也会更容易。

  当然,采用文件夹来分隔也同样可行,这是两种不同的风格,我会向你演示如何设计可以更方便的切换。

可复用能力

  对于一个稍大的项目,把特定业务模块、通用业务模块、通用技术类库放在同一个VS解决方案中,VS解决方案上的项目可能会达到上百个,编译速度将非常缓慢,导致很多不必要的麻烦。

  我之前已经多次提到,你可以把通用技术类和通用业务类从具体项目中分离出来,这样可以供多个项目使用,每个项目拥有自己的VS解决方案,共享相同的应用框架,这样维护会更容易,编译速度也更快。

  对于Applications.Managements项目示例,通用技术类库已经抽取到Util解决方案中,Applications.Managements不包含通用性的纯技术代码。

  我不会为你演示通用业务类的分离,因为代码示例太简单。

其它因素

  不同的应用程序类型也会影响VS解决方案的创建,比如创建WPF智能客户端应用程序,需要将应用层创建为WCF类库,这样可以将应用服务直接开放出来供WPF调用。对于WPF+WCF的架构,我后续也会进行介绍,如何通过IOC切换本地调用和远程调用,通过这个架构可以在开发时期采用本地方式调用,提高开发效率,部署时切换到WCF远程代理。

  如果你采用了诸如SOA架构,需要切割子系统部署成服务,可能需要创建更多类型的项目和多个VS解决方案,这些架构也对VS解决方案的创建具有相当影响。由于本人在SOA方面经验尚浅,待后续有更多经验再进行分享。

VS解决方案创建实战

  下面的步骤演示了我创建VS解决方案的习惯,你不一定要按我的步骤,只要最终达到你的要求即可。

创建表现层MVC项目

  打开VS解决方案,我使用的是VS 2013,自带了MVC4。

  创建MVC4项目,项目名称为Applications.Presentation.Managements,解决方案名称为Applications.Managements,MVC项目模板选择“基本”。

  先来讨论顶级空间的命名,即这里的Applications,要点是尽量抽象。顶级空间名称尽量不使用特定于项目或客户的名称,因为你做下一个项目时,需要大量更改命名空间。我采用Applications,代表抽象的应用程序,任何项目都是应用程序。你也可以采用公司的名称,比如你们公司简称为abc,那么可以这样Abc.Managements。

  Managements代表这是一个管理系统。Applications.Presentation.Managements说明它是管理系统的表现层,但为什么不用Applications.Managements.Presentation,后面介绍到领域层时我会说明这样做的原因。

  对于表现层来讲,没有其它层会调用它的API,所以我想保持表现层命名空间的简短,我耍了一个小技巧,将表现层的命名空间改成了Presentation。

  右键单击Applications.Presentation.Managements项目,选择“属性”,修改“默认命名空间”为Presetation,如下图所示。

  MVC创建完成后,会在根目录留下一个packages文件夹,MVC项目也会添加packages.config配置,这玩意很有用,Nuget会帮你管理依赖的程序集及版本,当别人运行你的解决方案时缺少程序集,会自动下载还原。但我更喜欢自己手工管理,在Applications.Managements根目录创建Libraries文件夹,我会把packages中必须的几个dll复制进去,其它全部删掉。

  当然,修改表现层默认命名空间和删除packages属于我的个人习惯,介绍这个是方便你看我的代码,对于你自己的项目,完全没必要这么麻烦。

  编译通过,继续下面的步骤,后面再返回到表现层。

创建表现层扩展项目

  在Applications.Managements解决方案上右键,“添加”->“新建项目”,创建一个类库项目,名称为Applications.Presentation.Managements.Extensions。

  这个项目用来为表现层提供一些支持,比如业务组件的封装。

  将它的默认命名空间改成Presentation,方便表现层的调用。

  下面来考虑类库输出的DLL目标位置,默认是在bin\Debug\,表示DLL将输出到类库项目的bin目录下Debug文件夹中。由于我们后续会创建更多的程序集,如果对输出位置不进行统一,将导致每个输出目录都产生大量重复的DLL。

  右键单击扩展类库,选择属性,找到“生成”选项卡的“输出路径“,修改为..\Release\,如下图所示。

  下面为Applications.Presentation.Managements项目添加Applications.Presentation.Managements.Extensions扩展项目的引用。

编译通过,继续下面的步骤。

创建应用层项目

  在Applications.Managements解决方案上创建类库项目,名称为Applications.Services,修改类库输出路径为..\Release\。

  应用层是为表现层提供服务的,所以表现层Applications.Presentation.Managements需要添加应用层Applications.Services的引用。

  编译通过,继续下面的步骤。

创建基础设施层项目

  DDD分层架构中没有了数据访问层的概念,被包含到基础设施层中。

  基础设施层是为其它各层服务的,按道理说,其它各层应该包含对基础设施层的引用。

  但是,为了让领域层变得更纯净,一般会应用依赖倒置原则,让基础设施层反过来依赖领域层。

  一些初学者会产生疑惑,这样不是造成循环引用的死循环了吗?下面谈下我的看法,不一定正确,仅供参考。

  在《领域驱动设计》一书中,对基础设施层的描述为:基础设施层为各层提供通用的技术能力

  可见基础设施层是一个抽象概念,诸如层超类型、公共操作类的封装、数据库的持久化,发邮件,发短信等操作,都是基础设施层的范畴。

  在我的代码中,大量通用技术,都被封装到Util相关的程序集中,如果需要合并VS解决方案,那么所有的Util项目都是基础设施层的一个组成部分。

  对于领域层与基础设施层的引用关系,与基础设施层中项目耦合性强弱有关,一般规律是:

  1. 领域层只引用基础设施层中低耦合的项目,比如领域层可以引用Util.Core、Util.Domains,这些项目只包含对.NET本身类库的引用,没有外部依赖,也不需要任何配置,领域层依赖这些项目不会降低可复用性和可测试性等指标。
  2. 与领域层密切相关的高耦合基础设施层项目,应用依赖倒置原则,先在领域层定义操作接口,由基础设施层项目引用相关领域层项目,并实现该接口。比如仓储代表聚合的集合,仓储的实现依赖于特定数据访问技术,甚至包含SQL语句,所以具有很高的耦合,且与领域层特定模块密切相关。如果领域层直接引用数据访问实现的程序集,将严重降低领域层的可复用性,且更难测试。
  3. 与领域层关系不大的高耦合基础设施层项目,应用分离接口模式,将操作接口与具体实现分离到基础设施层的不同项目中。比如工作单元的接口IApplicationUnitOfWork,它与领域层基本没啥关系,如果你的领域层只包含一个类库项目,把IApplicationUnitOfWork放到领域层项目中也没什么问题,我之前一直是这样干的,但如果你的领域层包含多个项目,你应该放到哪一个项目中?单独创建一个基础设施层项目来放置这些接口会好一些。

(未完待续…

代码更新

  1. 更新了js中的一些Bug
  2. 由于项目上需要使用MYSQL,最近几天摸索了EF操作MYSQL,遇到的一些障碍已解决,特将解决方案放出,供使用MYSQL的同学参考。

    a) MYSQL的乐观离线锁与SQL SERVER显著不同,主要参考王刚的这篇:EF6 Code First 系列 (三):在MySql中使用和SqlServer一致的RowVersion并发控制。不过对于Sql Server,我还是使用IsRowVersion,毕竟这是大部分项目的主打。

    b) 通过一个简单的Ioc配置,即可将Sql Server切换到MySql。

  c) MySql不支持Sql Server的schema,我使用.分隔MySql表名模拟schema,以保持与Sql Server的一致性风格,这需要一点EF映射技巧。

  3. codesmith代码生成模板已更新,调整了命名空间,并增加了对mysql特定配置的生成。

  4. 数据库备份中提供了一个MYSQL建库脚本。

QQ群

  应用程序框架交流QQ群1:386092459(已满)

  应用程序框架交流QQ群2:376124781

  EasyUi交流QQ群:157809322

源码下载:(下载时顺手推荐)

框架源码

项目示例源码

数据库备份

Codesmith生成器模板

备注

  本来准备只用一篇来完成本文,不过太忙了,只有分几次来写,希望各位见谅,下次更新的时间会比较长。

应用程序框架实战三十八:项目示例VS解决方案的创建(一)的更多相关文章

  1. 应用程序框架实战三十六:CRUD实战演练介绍

    从本篇开始,本系列将进入实战演练阶段. 前面主要介绍了一些应用程序框架的概念和基类,本来想把所有概念介绍完,再把框架内部实现都讲完了,再进入实战,这样可以让初学者基础牢靠.不过我的精力很有限,文章进度 ...

  2. 应用程序框架实战三十:表现层及ASP.NET MVC介绍(一)

    本文将介绍表现层及ASP.NET MVC的一些要点,特别是ASP.NET MVC的一些抽象和封装技巧,如果你对MVC还不了解,可以参考<ASP.NET MVC4 高级编程>,作者Jon G ...

  3. 应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较

    本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较. 领域实体为何不能一统江湖? 当你阅读 ...

  4. 微信小程序把玩(三十八)获取设备信息 API

    原文:微信小程序把玩(三十八)获取设备信息 API 获取设备信息这里分为四种, 主要属性: 网络信息wx.getNetWorkType, 系统信息wx.getSystemInfo, 重力感应数据wx. ...

  5. 应用程序框架实战二十二 : DDD分层架构之仓储(层超类型基础篇)

    前一篇介绍了仓储的基本概念,并谈了我对仓储的一些认识,本文将实现仓储的基本功能. 仓储代表聚合在内存中的集合,所以仓储的接口需要模拟得像一个集合.仓储中有很多操作都是可以通用的,可以把这部分操作抽取到 ...

  6. 【WePY小程序框架实战三】-组件传值

    [WePY小程序框架实战一]-创建项目 [WePY小程序框架实战二]-页面结构 父子组件传值 静态传值 静态传值为父组件向子组件传递常量数据,因此只能传递String字符串类型. 父组件 (paren ...

  7. 应用程序框架实战三十七:Util最新代码更新说明

    离上一篇又过去了一个月,时间比较紧,后续估计会更紧,所以这次将放出更多公共操作类及配套的CodeSmith模板,本篇将简要介绍新放出的重要功能,供有兴趣的同学参考. 重要更新 这一次对两个VS解决方案 ...

  8. 应用程序框架实战三十三:表现层及ASP.NET MVC介绍(二)

    最近的更新速度越来越慢,主要是项目上比较忙,封装EasyUi也要花很多时间.不过大家请放心,本系列不会半途夭折,并且代码干货也会持续更新.本文继续介绍表现层和Asp.net Mvc,我将在本篇讨论一些 ...

  9. 应用程序框架实战二十九:Util Demo介绍

    上文介绍了我选择EasyUi作为前端框架的原因,并发放了最新Demo.本文将对这个Demo进行一些介绍,以方便你能够顺利运行起来. 这个Demo运行起来以后,是EasyUi的一个简单CRUD操作,数据 ...

随机推荐

  1. java 的各种实用类库(jar包)

    总列表:# dom4j # org.json # pinyin4j # sqlite-jdbc # JavaMail # JLayer # dom4j 介绍:处理 xml 的类库.采用了 Java 集 ...

  2. normalize.css入门和下载

    CSS Reset 是革命党,CSS Reset 里最激进那一派提倡不管你小子有用没用,通通给我脱了那身衣服,凭什么你 body 出生就穿一圈 margin,凭什么你姓 h 的比别人吃得胖,凭什么你 ...

  3. webstorm2016注册码

    43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...

  4. python基础之day1

    Python 简介 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言. Python为我们提供了非常完善的基础代码库,覆盖了 ...

  5. 对象的this引用

    Java中的this关键字总是指向调用该方法的对象.根据this出现位置的不同,this作为对象的默认引用有两个功能: 1.构造器中引用该构造器正在初始化的对象. 2.在方法中引用调用该方法的对象. ...

  6. wampserver解决“不能切换在线”及运行“404问题”

    初次安装使用wampserver2.2,由于各个电脑安装的应用或是电脑型号不一样会出现以下问题: 1.安装后,不能出切换“服务器在线”或是“服务器离线” 2.设置站点后,运行编写好的代码出现404错误 ...

  7. 利用结果集元数据将查询结果封装为map

    package it.cast.jdbc; import java.sql.Connection; import java.sql.ParameterMetaData; import java.sql ...

  8. Microsoft dotnetConf 2015 一些整理

    dotnetConf 2015 直播计划: 第一天 (10 个主讲) - .NET Product Teams 主讲人为 .NET 产品开发团队,.NET 产品主要包含 .NET Core.ASP.N ...

  9. 类库间无项目引用时,在编译时拷贝DLL

    例一: xcopy $(TargetPath) $(SolutionDir)\Framework\HCSP.App\bin\Debug /y 例二: xcopy $(TargetPath) $(Sol ...

  10. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...