0. 前言

在《asp.net core 系列》之前的几篇文章中,我们简单了解了路由、控制器以及视图的关系以及静态资源的引入,让我们对于asp.net core mvc项目有了基本的认识。不过,这些并不是 asp.net core mvc项目的全部内容,剩下的内容我将结合实战项目为大家讲解其中的知识。现在,就让我们开始吧。

1. 项目构建

抛开之前的项目,现在跟着我重新创建一个项目,第一步依旧是先创建一个解决方案:

dotnet new sln --name Template

我先介绍一下这个项目(指整个项目,不是单独的asp.net core 应用),这是一个后台管理的模板应用,提供了常见后台系统(管理员端)的功能,包括员工管理、部门管理、角色管理等功能。

现在回到项目中,通常一个项目需要一个模型层,一个数据提供层以及web展示层。然后,我们依次创建 Data、Domain、Web 三个项目,其中Data和Domain 是 classlib,Web是mvc项目。

# 确保当前目录与 Template.sln 处于相同的目录
dotnet new classlib --name Data
dotnet new classlib --name Domain
dotnet new mvc --name Web

添加三个项目到解决方案中:

dotnet sln add Data
dotnet sln add Domain
dotnet sln add Web

因为Data 中存放着模型层,所以需要其他项目对它有一个引用:

cd Domain
dotnet add reference ../Data
cd ../Web
dotnet add reference ../Data

当然,实际开发中我们应当还有一个Service层,这一层用来存放业务代码,减少控制器里不必要的业务代码。那么继续:

# 回到项目的根目录
cd ..
dotnet new classlib --name Service
dotnet sln add Service

然后添加Service的引用:

cd Service
dotnet add reference ../Data

将 Service的引用添加到Web里:

cd ../Web
dotnet add reference ../Service

现在一个大型工程基本都是面向接口编程,几个关键层应当都是接口层,我们实际上还缺少Domain的实现层和Service的实现层。

cd ..
dotnet new classlib --name Domain.Implements
dotnet new classlib --name Service.Implements

在对应的实现层中,引入它们实现的接口层,并引入Data:

cd Domain.Implements
dotnet add reference ../Data
dotnet add reference ../Domain
cd ../Service.Implements
dotnet add reference ../Data
dotnet add reference ../Domain
dotnet add reference ../Service

这里在Service的实现层添加Domain接口层的引用,而不是实现层的引用。这是因为面向接口编程,我们需要对Service实现层隐藏Domain的实现,所以对于Service的实现层来说,不需要关心Domain层的实现逻辑。

在Web中添加新建的两个实现层的引用:

cd ../Web
dotnet add reference ../Domain.Implements
dotnet add reference ../Service.Implements

添加这两个实现层到解决方案中:

cd ..
dotnet sln add Domain.Implements
dotnet sln add Service.Implements

下图是到目前为止的项目结构图:

整体而言,Data是各个层之间的数据流通依据,所以各个项目都依赖于此项目,各个接口层的实现层都只对Web可见,其他各层实际上并不清楚具体实现。

隐藏实现层有什么好处呢?

  • 调用方不知道实现方的逻辑,避免调用方对特定实现的依赖
  • 有利于团队协作,有的团队是针对模块划分,有的是针对分层划分,无论哪种,使用接口都是一个好的选择
  • 有利于后期优化,可以很方便的切换实现层,而不用重新编译过多的代码

当然,并不只有这些好处,不过这样有一个坏处,在web层调用service层时会更繁琐,不过这也不是不可解决的,后续的内容中会为大家介绍如何解决这个烦恼。

2. 项目补充

通常情况下,一个完整的项目还会有一个工具类项目和一个测试项目。所以,继续添加以下项目:

dotnet new classlib --name Utils

Utils 表示工具类,通常一个项目中工具类会比较多,所以就抽成了一个项目,单独列出来。

添加测试项目:

dotnet new nunit --name Test

这里使用的是nunit 3测试框架,当然还有另一个是xunit测试框架。

添加两个项目到解决方案里:

dotnet sln add Utils
dotnet sln add Test

3. 总结

本章内容旨在通过创建项目,让大家了解实际开发中项目的层级规划思想,这并不代表我的就是最优的,只是这是我总结出来相对方便的层级关系。这里并没有讲解如何通过Visual Studio或者Rider创建这样的一个项目,我希望大伙能够自己试试。

好了,希望大家能创建好项目,当然了后期我会给大家提供这个项目的源码的,地址暂时保密哦。

更多内容烦请关注我的博客《高先生小屋》

【asp.net core 系列】6 实战之 一个项目的完整结构的更多相关文章

  1. ASP.NET Core 系列视频完结,新项目实战课程发布。

    今天把MVC的章节完成了,给大家从头到尾做了一个登录注册的示例,带前后端Model验证,算是完整的示例.同时借助于eShopOnContainers的示例也做了一个DBContextSeed的包装器来 ...

  2. asp.net core系列 59 Ocelot 构建基础项目示例

    一.入门概述 从这篇开始探讨Ocelot,Ocelot是一个.NET API网关,仅适用于.NET Core,用于.NET面向微服务/服务的架构中.当客户端(web站点.ios. app 等)访问we ...

  3. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  4. 【asp.net core 系列】8 实战之 利用 EF Core 完成数据操作层的实现

    0. 前言 通过前两篇,我们创建了一个项目,并规定了一个基本的数据层访问接口.这一篇,我们将以EF Core为例演示一下数据层访问接口如何实现,以及实现中需要注意的地方. 1. 添加EF Core 先 ...

  5. 【asp.net core 系列】10 实战之ActionFilter

    0.前言 在上一篇中,我们提到了如何创建一个UnitOfWork并通过ActionFilter设置启用.这一篇我们将简单介绍一下ActionFilter以及如何利用ActionFilter,顺便补齐一 ...

  6. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  7. ASP.NET Core系列(二):创建第一个.Net Core 项目

    前面讲过 .NET Core简介及开发环境安装,本章会讲一讲ASP.NET Core 2.0的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zh ...

  8. Asp.Net Core 中IdentityServer4 实战之角色授权详解

    一.前言 前几篇文章分享了IdentityServer4密码模式的基本授权及自定义授权等方式,最近由于改造一个网关服务,用到了IdentityServer4的授权,改造过程中发现比较适合基于Role角 ...

  9. 【asp.net core 系列】 1 带你了解一下asp.net core

    0. 前言 这是一个新的系列,名字是<ASP.NET Core 入门到实战>.这个系列主讲ASP.NET Core MVC,辅助一些前端的基础知识(能用来实现我们需要的即可,并非主讲).同 ...

随机推荐

  1. Spring Boot 之 Spring Batch 批处理实践

    实践内容 从 MariaDB 一张表内读 10 万条记录,经处理后写到 MongoDB . 具体实现 1.新建 Spring Boot 应用,依赖如下: <!-- Web 应用 --> & ...

  2. 笨办法学习python之hashmap

    #!/user/bin/env python #-*-coding:utf-8 -*- #Author: qinjiaxi #初始化aMap列表,把列表num_buckets添加到aMap中,num_ ...

  3. 「雕爷学编程」Arduino动手做(29)——DS1302时钟模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  4. JavaScript和TypeScript的区别和联系

    转载自:http://web.jobbole.com/93618/?utm_source=group.jobbole.com&utm_medium=relatedArticles JavaSc ...

  5. 前后端分离产生的跨域问题的解决方案之--jsonp、nginx代理、设置头信息等

    前言 在前后端没有分离的时候,前端开发要么是写静态页面,数据渲染后端来做,要么就是前端的页面和后端的代码刚开始的时候就合并在一起,每次后端代码更新了之后,前端也要更新一下代码,然后重启一下服务,还是比 ...

  6. 大清朝早亡了,还没有入门 Spring Boot?

    由于读者的数量越来越多,难免会被问到一些我自己都觉得不好意思的问题,比如说前几天小王就问我:"二哥,快教教我,怎么通过 Spring Boot 创建一个 Hello World 项目啊?&q ...

  7. poj1149 经典建模

    http://wenku.baidu.com/view/0ad00abec77da26925c5b01c.html 以上内容均为转载 #include<queue> #include< ...

  8. poi--读取不同类型的excel表格

    要想根据不同类型excel表格获取其数据,就要先判断其表格类型 poi-api种方法: getCellType    public int getCellType()        Return th ...

  9. 有点干货 | Jdk1.8新特性实战篇(41个案例)

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获!

  10. 使用容器化块存储OpenEBS在K3s中实现持久化存储

    作者简介 Giridhara Prasad,Mayadata Inc.首席工程师.在软件测试自动化.混沌工程(chaos engineering)方面有丰富的经验.目前,他正在研究开源混沌工程项目Li ...