安徽做公司网站哪家好,珠宝网站策划,做网站都用什么技术,网站设计规划的一般流程在正式进入主题之前我们来看下几个概念#xff1a; 一、依赖倒置 依赖倒置是编程五大原则之一#xff0c;即#xff1a; 1、上层模块不应该依赖于下层模块#xff0c;它们共同依赖于一个抽象。 2、抽象不能依赖于具体#xff0c;具体依赖于抽象。 其中上层就是指使用者 一、依赖倒置 依赖倒置是编程五大原则之一即 1、上层模块不应该依赖于下层模块它们共同依赖于一个抽象。 2、抽象不能依赖于具体具体依赖于抽象。 其中上层就是指使用者下层就是指被使用者。 二、IoC控制反转 控制反转IoC全称Inversion of Control是一种思想所谓“控制反转”就是反转获得依赖对象的过程。 三、依赖注入DI 依赖注入设计模式是一种在类及其依赖对象之间实现控制反转IoC思想的技术。 所谓依赖注入DI全称Dependency Injection就是由IoC容器在运行期间动态地将某种依赖关系注入到对象之中。 依赖注入主要分为3种构造函数注入、属性注入、方法注入。 这里就不做过多的描述如果有机会会通过具体例子再和大家分享下面我们正式进入本章主题。 PSASP.NET Core 内置的IoC容器目前只支持构造函数注入以下我们也主要讲解构造函数注入的方式。 话不多说直入主题看我们的解决方案结构 分别对上面的工程进行简单的说明 1、TianYa.DotNetShare.Model为demo的实体层 2、TianYa.DotNetShare.Repository为demo的仓储层即数据访问层 3、TianYa.DotNetShare.Service为demo的服务层即业务逻辑层 4、TianYa.DotNetShare.CommTool为demo的公共工具类库 5、TianYa.DotNetShare.SharpCore为demo的Sharp核心类库 6、TianYa.DotNetShare.CoreMvcDemo为demo的web层项目MVC框架 约定 1、公共的类库我们选择.NET Standard 2.0作为目标框架可与Framework进行共享。 2、本demo的web项目为ASP.NET Core Web 应用程序.NET Core 2.2 MVC框架。 一、实体层 1、新建一个学生实体 Student using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.Model
{/// summary/// 学生类/// /summarypublic class Student{/// summary/// 学号/// /summarypublic string StuNo { get; set; }/// summary/// 姓名/// /summarypublic string Name { get; set; }/// summary/// 年龄/// /summarypublic int Age { get; set; }/// summary/// 性别/// /summarypublic string Sex { get; set; }}
} demo中的实体就这样了 二、仓储层 本demo的仓储层需要引用我们的实体层TianYa.DotNetShare.Model 为什么选择用仓储原因很简单方便我们进行个性化扩展。在数据操作的底层进行其他个性化逻辑处理。 约定 1、接口的定义放在根目录下接口的实现类统一放到Impl文件夹表示实现类目录。 2、每个实体对应一个仓储的接口和实现类即有多少个实体就对应创建多少个接口和实现类。 3、仓储层接口都以“I”开头以“Repository”结尾。仓储层实现都以“Repository”结尾。 我们新建一个Student的仓储接口IStudentRepository.cs using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository
{/// summary/// 学生类仓储层接口/// /summarypublic interface IStudentRepository{/// summary/// 根据学号获取学生信息/// /summary/// param namestuNo学号/param/// returns学生信息/returnsStudent GetStuInfo(string stuNo);}
} 接着在Impl中新建一个Student的仓储实现StudentRepository.cs using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository.Impl
{/// summary/// 学生类仓储层/// /summarypublic class StudentRepository : IStudentRepository{/// summary/// 根据学号获取学生信息/// /summary/// param namestuNo学号/param/// returns学生信息/returnspublic Student GetStuInfo(string stuNo){//数据访问逻辑此处为了演示就简单些var student new Student();switch (stuNo){case 10000:student new Student() { StuNo 10000, Name 张三, Sex 男, Age 20 };break;case 10001:student new Student() { StuNo 10001, Name 钱七七, Sex 女, Age 18 };break;case 10002:student new Student() { StuNo 10002, Name 李四, Sex 男, Age 21 };break;default:student new Student() { StuNo 10003, Name 王五, Sex 男, Age 25 };break;}return student;}}
} 该类实现了IStudentRepository接口 三、服务层 本demo的服务层需要引用我们的实体层TianYa.DotNetShare.Model和我们的仓储层TianYa.DotNetShare.Repository 服务层与仓储层类似它属于仓储层的使用者。定义的方式也与仓储层类似有接口和Impl实现目录。 但服务层不需要一个实体对应一个服务层更多的是按照功能模块进行划分比如一个登录模块创建一个LoginService。 约定 1、服务层接口都以“I”开头以“Service”结尾。服务层实现都以“Service”结尾。 为了演示我们新建一个Student的服务层接口IStudentService.cs using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Service
{/// summary/// 学生类服务层接口/// /summarypublic interface IStudentService{/// summary/// 根据学号获取学生信息/// /summary/// param namestuNo学号/param/// returns学生信息/returnsStudent GetStuInfo(string stuNo);}
} 接着我们同样在Impl中新建一个Student的服务层实现StudentService.cs using System;
using System.Collections.Generic;
using System.Text;using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository;namespace TianYa.DotNetShare.Service.Impl
{/// summary/// 学生类服务层/// /summarypublic class StudentService : IStudentService{/// summary/// 定义仓储层学生抽象类对象/// /summaryprotected IStudentRepository StuRepository;/// summary/// 空构造函数/// /summarypublic StudentService() { }/// summary/// 构造函数/// /summary/// param namestuRepository仓储层学生抽象类对象/parampublic StudentService(IStudentRepository stuRepository){this.StuRepository stuRepository;}/// summary/// 根据学号获取学生信息/// /summary/// param namestuNo学号/param/// returns学生信息/returnspublic Student GetStuInfo(string stuNo){var stu StuRepository.GetStuInfo(stuNo);return stu;}}
} 该类实现了IStudentService接口 四、公共工具类库 公共工具类库就是将来我们要在里面写各种各样的帮助类以提高程序的可复用性此处就不做赘述。 五、Sharp核心类库 需要从NuGet上引用以下几个程序集 Sharp核心类库为公共的基础类最底层。 其中Model文件夹为实体目录主要存放数据库连接相关的实体。Extensions文件夹为扩展目录主要存放最底层的扩展类我们底层的批量依赖注入就放在这里面。 在Model实体目录中我们新建一个用于数据库连接的接口IDataBaseSetting.cs using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.SharpCore.Model
{public interface IDataBaseSetting{/// summary/// 访问数据库连接串/// /summarystring ConnectionString { get; set; }/// summary/// 数据库名称当是关系型数据库时DatabaseName属性没用到/// /summarystring DatabaseName { get; set; }}
} 接着添加一个用于数据库连接的实现类DataBaseSetting.cs using System;
using System.Collections.Generic;
using System.Text;namespace TianYa.DotNetShare.SharpCore.Model
{public class DataBaseSetting : IDataBaseSetting{/// summary/// 访问数据库连接串/// /summarypublic string ConnectionString { get; set; }/// summary/// 数据库名称当是关系型数据库时DatabaseName属性没用到/// /summarypublic string DatabaseName { get; set; }}
} 该类实现了IDataBaseSetting.cs接口 Model实体目录主要用于以后涉及到数据库访问的时候使用本demo主要为了简单介绍下如何使用ASP.NET Core内置的IoC容器DI进行批量依赖注入故没有对该实体目录进行详细的讲解。 接下来就是重头戏了我们在Extensions扩展目录中添加一个用于批量依赖注入的扩展类ServiceCollectionExtensions.cs using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;using TianYa.DotNetShare.SharpCore.Model;namespace TianYa.DotNetShare.SharpCore.Extensions
{/// summary/// ServiceCollection扩展/// /summarypublic static class ServiceCollectionExtensions{#region 通过反射批量注入指定的程序集/// summary/// 通过反射批量注入指定的程序集/// /summary/// param nameservices服务/param/// param nameassemblyNames程序集数组 如:[TianYa.DotNetShare.Repository,TianYa.DotNetShare.Service]无需写dll/parampublic static void RegisterTianYaSharpService(this IServiceCollection services, params string[] assemblyNames){foreach (string assemblyName in assemblyNames){foreach (var itemClass in GetClassInterfacePairs(assemblyName)){foreach (var itemInterface in itemClass.Value){if (itemInterface ! typeof(DataBaseSetting)){services.AddTransient(itemInterface, itemClass.Key); //DI依赖注入}}}}}#endregion#region DI依赖注入辅助方法/// summary/// 获取类以及类实现的接口键值对/// /summary/// param nameassemblyName程序集名称/param/// returns类以及类实现的接口键值对/returnsprivate static DictionaryType, ListType GetClassInterfacePairs(string assemblyName){//存储 实现类 以及 对应接口DictionaryType, ListType dic new DictionaryType, ListType();Assembly assembly GetAssembly(assemblyName);if (assembly ! null){Type[] types assembly.GetTypes();foreach (var item in types.AsEnumerable().Where(x !x.IsAbstract !x.IsInterface !x.IsGenericType)){dic.Add(item, item.GetInterfaces().Where(x !x.IsGenericType).ToList());}}return dic;}/// summary/// 获取所有的程序集/// /summary/// returns程序集集合/returnsprivate static ListAssembly GetAllAssemblies(){var list new ListAssembly();var deps DependencyContext.Default;var libs deps.CompileLibraries.Where(lib !lib.Serviceable lib.Type ! package);//排除所有的系统程序集、Nuget下载包foreach (var lib in libs){try{var assembly AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));list.Add(assembly);}catch (Exception){// ignored}}return list;}/// summary/// 获取指定的程序集/// /summary/// param nameassemblyName程序集名称/param/// returns程序集/returnsprivate static Assembly GetAssembly(string assemblyName){return GetAllAssemblies().FirstOrDefault(assembly assembly.FullName.Contains(assemblyName));}#endregion}
} 并且添加一个Dynamic的扩展类DynamicExtensions.cs using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Xml;namespace TianYa.DotNetShare.SharpCore.Extensions
{/// summary/// Dynamic的扩展方法/// /summarypublic static class DynamicExtensions{#region 匿名对象处理#region 将对象[主要是匿名对象]转换为dynamic/// summary/// 将对象[主要是匿名对象]转换为dynamic/// /summarypublic static dynamic ToDynamic(this object value){IDictionarystring, object expando new ExpandoObject();var type value.GetType();var properties TypeDescriptor.GetProperties(type);foreach (PropertyDescriptor property in properties){var val property.GetValue(value);if (property.PropertyType.FullName.StartsWith(f__AnonymousType)){dynamic dval val.ToDynamic();expando.Add(property.Name, dval);}else{expando.Add(property.Name, val);}}return expando as ExpandoObject;}#endregion#region 将对象[主要是匿名对象]转换为Listdynamic/// summary/// 将对象[主要是匿名对象]转换为Listdynamic/// /summarypublic static Listdynamic ToDynamicList(this IEnumerabledynamic values){var list new Listdynamic();if (values ! null){if (values.Any()){list.AddRange(values.Select(v ((object)v).ToDynamic()));}}return list;}#endregion#region 将匿名对象集合转换为XML/// summary/// 将匿名对象集合转换为XML/// /summarypublic static XmlDocument ListObjertToXML(this IEnumerabledynamic values){var xmlDoc new XmlDocument();var xmlElem xmlDoc.CreateElement(DocumentElement);xmlDoc.AppendChild(xmlElem);if (values ! null){if (values.Any()){var node xmlDoc.SelectSingleNode(DocumentElement);foreach (var item in values){var xmlRow xmlDoc.CreateElement(Row);ObjectToXML(item, xmlDoc, xmlRow);node.AppendChild(xmlRow);}}}return xmlDoc;}#endregion#region 将匿名对象填充XML节点/// summary/// 将匿名对象填充XML节点/// /summaryprivate static void ObjectToXML(object value, XmlDocument xmlDoc, XmlElement xmlRow){IDictionarystring, object expando new ExpandoObject();var type value.GetType();var properties TypeDescriptor.GetProperties(type);foreach (PropertyDescriptor property in properties){var val property.GetValue(value);xmlRow.CloneNode(false);var xmlTemp xmlDoc.CreateElement(property.Name);XmlText xmlText;if (property.PropertyType.FullName.StartsWith(f__AnonymousType)){dynamic dval val.ToDynamic();xmlText xmlDoc.CreateTextNode(dval.ObjectToString());}else{xmlText xmlDoc.CreateTextNode(val.ToString());}xmlTemp.AppendChild(xmlText);xmlRow.AppendChild(xmlTemp);}}#endregion#endregion}
} 该扩展类主要在我们的Action向视图传递匿名类型值的时候使用 六、Web层 本demo的web项目需要引用以下几个程序集 1、TianYa.DotNetShare.Model 我们的实体层 2、TianYa.DotNetShare.Service 我们的服务层 3、TianYa.DotNetShare.Repository 我们的仓储层正常我们的web项目是不应该使用仓储层的此处我们引用是为了演示IoC依赖注入 4、TianYa.DotNetShare.CommTool 我们的公共工具类库 5、TianYa.DotNetShare.SharpCore 我们的Sharp核心类库 到了这里我们所有的工作都已经准备好了接下来就是开始做注入工作了。 打开我们的Startup.cs文件进行注入工作 using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;using TianYa.DotNetShare.SharpCore.Extensions;namespace TianYa.DotNetShare.CoreMvcDemo
{public class Startup{public Startup(IConfiguration configuration){Configuration configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.ConfigureCookiePolicyOptions(options {// This lambda determines whether user consent for non-essential cookies is needed for a given request.options.CheckConsentNeeded context true;options.MinimumSameSitePolicy SameSiteMode.None;});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);//DI依赖注入批量注入指定的程序集services.RegisterTianYaSharpService(new string[] { TianYa.DotNetShare.Repository, TianYa.DotNetShare.Service });}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler(/Home/Error);}app.UseStaticFiles();app.UseCookiePolicy();app.UseMvc(routes {routes.MapRoute(name: default,template: {controllerHome}/{actionIndex}/{id?});});}}
} 其中用来实现批量依赖注入的只要一句话就搞定了如下所示 //DI依赖注入批量注入指定的程序集
services.RegisterTianYaSharpService(new string[] { TianYa.DotNetShare.Repository, TianYa.DotNetShare.Service }); Sharp核心类库在底层实现了批量注入的逻辑程序集的注入必须按照先后顺序进行先进行仓储层注入然后再进行服务层注入。 接下来我们来看看控制器里面怎么弄 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;using TianYa.DotNetShare.CoreMvcDemo.Models;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Repository;namespace TianYa.DotNetShare.CoreMvcDemo.Controllers
{public class HomeController : Controller{/// summary/// 定义仓储层学生抽象类对象/// /summaryprotected IStudentRepository StuRepository;/// summary/// 定义服务层学生抽象类对象/// /summaryprotected IStudentService StuService;/// summary/// 通过构造函数进行注入/// 注意参数是抽象类而非实现类因为已经在Startup.cs中将实现类映射给了抽象类/// /summary/// param namestuRepository仓储层学生抽象类对象/param/// param namestuService服务层学生抽象类对象/parampublic HomeController(IStudentRepository stuRepository, IStudentService stuService){this.StuRepository stuRepository;this.StuService stuService;}public IActionResult Index(){var stu1 StuRepository.GetStuInfo(10000);var stu2 StuService.GetStuInfo(10001);string msg $学号10000姓名{stu1.Name}性别{stu1.Sex}年龄{stu1.Age}br /;msg $学号10001姓名{stu2.Name}性别{stu2.Sex}年龄{stu2.Age};return Content(msg, text/html, System.Text.Encoding.UTF8);}public IActionResult Privacy(){return View();}[ResponseCache(Duration 0, Location ResponseCacheLocation.None, NoStore true)]public IActionResult Error(){return View(new ErrorViewModel { RequestId Activity.Current?.Id ?? HttpContext.TraceIdentifier });}}
} 至此完成处理接下来就是见证奇迹的时刻了我们来访问一下/home/index看看是否能返回学生信息。 我们可以发现返回了学生的信息说明我们注入成功了。 另外通过这个例子我们可以发现在注入仓储层对象StudentRepository时不仅控制器中注入成功了而且在服务层中也注入成功了说明我们ASP.NET Core内置的IoC容器DI依赖注入是全局的。 总结 1、采用的是构造函数注入的方式在构造函数中初始化赋值。 2、ASP.NET Core内置的IoC容器DI依赖注入是全局的。 3、DI批量依赖注入的核心思想就是根据程序集的名称通过反射获取类以及类实现的接口键值对字典然后通过循环进行批量注入。 扩展DI生命周期 生命周期是依赖注入设计原则里一个非常重要的概念ASP.NET Core 一共有3种生命周期。 1、暂时Transient顾名思义这种生命周期的对象是暂时的每次请求都会创建一个新的实例。 services.AddTransientIStudentRepository, StudentRepository();
services.AddTransientIStudentService, StudentService(); 2、作用域Scoped每次请求使用的是同一个实例。 services.AddScopedIStudentRepository, StudentRepository();
services.AddScopedIStudentService, StudentService(); 3、单例Singleton第一次请求时就创建以后每次请求都是使用相同的实例。 services.AddSingletonIStudentRepository, StudentRepository();
services.AddSingletonIStudentService, StudentService(); 官方文档建议依赖注入是静态/全局对象访问模式的替代方法如果将其与静态对象访问混合使用则可能无法实现依赖关系注入的优点。 至此本章就介绍完了如果你觉得这篇文章对你有所帮助请记得点赞哦谢谢 demo源码 链接https://pan.baidu.com/s/17GIgvp0JWy8BaNOE8l6p9A
提取码i9hh 参考博文https://www.cnblogs.com/fei686868/p/11077997.html 版权声明如有雷同纯属巧合如有侵权请及时联系本人修改谢谢 转载于:https://www.cnblogs.com/xyh9039/p/11373269.html