.netCore+Vue 搭建的简捷开发框架 (5)

vue

文章目录:.netCore+Vue 搭建的简捷开发框架--目录

比奇小说网 m.biqi.org

上两节的内容介绍了一些关于。netCore 相关的一些基础知识。介绍这些的目的,最主要的还是为了我们的架构搭建服务。

上一节中,我们介绍了有关NetCore DI的一些概念。 整个框架,我们的仓储层、服务层都是通过依赖注入的方式进行加载调用的。

下面就来看一下仓储层和服务层是如何注入的:

 1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Threading.Tasks;

5 using Microsoft.AspNetCore.Builder;

6 using Microsoft.AspNetCore.Hosting;

7 using Microsoft.AspNetCore.Mvc;

8 using Microsoft.EntityFrameworkCore;

9 using Microsoft.Extensions.Configuration;

10 using Microsoft.Extensions.DependencyInjection;

11 using Microsoft.Extensions.Logging;

12 using Microsoft.Extensions.Options;

13 using Sincere.Core.IRepository.Base;

14 using Sincere.Core.IServices.Base;

15 using Sincere.Core.Model.EFCore;

16 using Sincere.Core.Model.Models;

17 using Sincere.Core.Repository.Base;

18 using Sincere.Core.Services.Base;

19 using Sincere.Core.WebAPI.ServiceExtension;

20

21 namespace Sincere.Core.WebAPI

22 {

23 public class Startup

24 {

25 public Startup(IConfiguration configuration)

26 {

27 Configuration = configuration;

28 }

29

30 public IConfiguration Configuration { get; }

31

32 // This method gets called by the runtime. Use this method to add services to the container.

33 public void ConfigureServices(IServiceCollection services)

34 {

35 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

36

37 services.AddDbContextPool<BaseCoreContext>(options =>

38 options.UseSqlServer(BaseDBConfig.ConnectionString));

39 services.AddScoped<IBaseContext, BaseCoreContext>();

40 //泛型引用方式

41 services.AddScoped(typeof(IBaseServices<>), typeof(BaseServices<>));

42

43 services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));

44

45 services.RegisterAssembly("IServices");

46 services.RegisterAssembly("IRepository");

47 }

48

49 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

50 public void Configure(IApplicationBuilder app, IHostingEnvironment env)

51 {

52 if (env.IsDevelopment())

53 {

54 app.UseDeveloperExceptionPage();

55 }

56

57 app.UseMvc();

58 }

59 }

60 }

View Code

 标记1 的部分,是关于EF,以及DbContext 的相关引用,这里涉及到一个AddDbContextPool的概念,我个人的理解就是可以把他当成我们使用ADO.net 时的数据库连接池。

另外需要说明的一点就是,采用AddScoped 的方式,整个数据库链接的上下文,在整个请求过程中,只会被实例化一次。

标记2的部分,时我们对仓储的基础类,和服务层基础类的引用,注意这些基础类是泛型的方式,所以引用的时候,需要采用泛型的方式来实现。在这个地方,刚开始的时候,不知道AddScoped支持泛型的方式,还写过一个工厂类来进行注入。

剩下的方法,services.RegisterAssembly 其实是一个比较巧妙的方式,为了避免每写一个service、repository就在ConfigureServices中注入一次。所以在这里采用了反射的机制。利用反射和我们的约定,将整个程序集中的Service和Repository进行一个引用。

webAPI工程下新建一个ServiceExtension目录,并添加RuntimeHelper类和ServiceExtension。

如下图:

 代码如下:

 1 using Microsoft.Extensions.DependencyInjection;

2 using System;

3 using System.Collections.Generic;

4 using System.Linq;

5 using System.Reflection;

6 using System.Threading.Tasks;

7

8 namespace Sincere.Core.WebAPI.ServiceExtension

9 {

10 /// <summary>

11 /// IServiceCollection扩展

12 /// </summary>

13 /// <summary>

14 /// IServiceCollection扩展

15 /// </summary>

16 public static class ServiceExtension

17 {

18 /// <summary>

19 /// 用DI批量注入接口程序集中对应的实现类。

20 /// <para>

21 /// 需要注意的是,这里有如下约定:

22 /// IUserService --> UserService, IUserRepository --> UserRepository.

23 /// </para>

24 /// </summary>

25 /// <param name="service"></param>

26 /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>

27 /// <returns></returns>

28 public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)

29 {

30 if (service == null)

31 throw new ArgumentNullException(nameof(service));

32 if (string.IsNullOrEmpty(interfaceAssemblyName))

33 throw new ArgumentNullException(nameof(interfaceAssemblyName));

34

35 var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);

36 if (assembly == null)

37 {

38 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");

39 }

40

41 //过滤掉非接口及泛型接口

42 var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);

43

44 foreach (var type in types)

45 {

46 var implementTypeName = type.Name.Substring(1);

47 var implementType = RuntimeHelper.GetImplementType(implementTypeName, type);

48 if (implementType != null)

49 {

50 switch (serviceLifetime)

51 {

52 //根据条件,选择注册依赖的方法

53 case ServiceLifetime.Scoped:

54 //将获取到的接口和类注册进去

55 service.AddScoped(type, implementType);

56 break;

57 case ServiceLifetime.Singleton:

58 service.AddSingleton(type, implementType);

59 break;

60 case ServiceLifetime.Transient:

61 service.AddTransient(type, implementType);

62 break;

63 }

64

65 }

66 }

67 return service;

68 }

69

70

71 }

72 }

ServiceExtension.cs

 1 using Microsoft.Extensions.DependencyModel;

2 using System;

3 using System.Collections.Generic;

4 using System.Linq;

5 using System.Reflection;

6 using System.Runtime.Loader;

7 using System.Threading.Tasks;

8

9 namespace Sincere.Core.WebAPI.ServiceExtension

10 {

11 public class RuntimeHelper

12 {

13 /// <summary>

14 /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包

15 /// </summary>

16 /// <returns></returns>

17 public static IList<Assembly> GetAllAssemblies()

18 {

19 var list = new List<Assembly>();

20 var deps = DependencyContext.Default;

21 var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包

22 foreach (var lib in libs)

23 {

24 try

25 {

26 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));

27 list.Add(assembly);

28 }

29 catch (Exception)

30 {

31 // ignored

32 }

33 }

34 return list;

35 }

36

37 public static Assembly GetAssembly(string assemblyName)

38 {

39 return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));

40 }

41

42 public static IList<Type> GetAllTypes()

43 {

44 var list = new List<Type>();

45 foreach (var assembly in GetAllAssemblies())

46 {

47 var typeInfos = assembly.DefinedTypes;

48 foreach (var typeInfo in typeInfos)

49 {

50 list.Add(typeInfo.AsType());

51 }

52 }

53 return list;

54 }

55

56 public static IList<Type> GetTypesByAssembly(string assemblyName)

57 {

58 var list = new List<Type>();

59 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));

60 var typeInfos = assembly.DefinedTypes;

61 foreach (var typeInfo in typeInfos)

62 {

63 list.Add(typeInfo.AsType());

64 }

65 return list;

66 }

67

68 public static Type GetImplementType(string typeName, Type baseInterfaceType)

69 {

70 return GetAllTypes().FirstOrDefault(t =>

71 {

72 if (t.Name == typeName &&

73 t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))

74 {

75 var typeInfo = t.GetTypeInfo();

76 return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;

77 }

78 return false;

79 });

80 }

81 }

82 }

RuntimeHelper.cs

 这样类似的代码网上挺多的。大家可以参考借鉴一下。另外这个地方其实不用太过于关心反射带来的性能问题,因为只有在程序启动的时候,加载一次。

仓储层和服务层都注入进来以后,接下来就是怎么去使用了。

来一起看一下我们是怎么在ValuesController里面进行实现的。

  1.定义服务层接口

 2.在ValuesController初始化的时候,将服务层接口注入进来。

 3.使用接口,调用数据。

代码如下:

 1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Threading.Tasks;

5 using Microsoft.AspNetCore.Mvc;

6 using Sincere.Core.IServices;

7

8 namespace Sincere.Core.WebAPI.Controllers

9 {

10 [Route("api/[controller]")]

11 [ApiController]

12 public class ValuesController : ControllerBase

13 {

14 readonly IAdvertisementServices _advertisementServices;

15 public ValuesController(IAdvertisementServices advertisementServices)

16 {

17 _advertisementServices = advertisementServices;

18 }

19

20 // GET api/values

21 [Route("")]

22 [HttpGet]

23 public async Task<ActionResult<IEnumerable<string>>> Get()

24 {

25 var t = await _advertisementServices.ReadAllAd();

26

27 return new string[] { "value1", "value2" };

28 }

29

30 // GET api/values/5

31 [HttpGet("{id}")]

32 public ActionResult<string> Get(int id)

33 {

34 return "value";

35 }

36

37 // POST api/values

38 [HttpPost]

39 public void Post([FromBody] string value)

40 {

41 }

42

43 // PUT api/values/5

44 [HttpPut("{id}")]

45 public void Put(int id, [FromBody] string value)

46 {

47 }

48

49 // DELETE api/values/5

50 [HttpDelete("{id}")]

51 public void Delete(int id)

52 {

53 }

54 }

55 }

View Code

关于ReadAllAd()方法,之前的章节中已经有过描述。

 调用成功,说明框架的整体流程已经跑通了!晚上加个鸡腿,庆祝一下!

按照之前的脑图,不知道大家还记得不?

红框里面的内容,到这一节,基本就结束了。接下来,会逐步的丰富我们的框架。加入日志,异常处理,权限验证。以及其他脑图中列出来的内容。

希望整个过程对于想学习、了解netCore 的同学们有所帮助!

 源码已经更新:https://github.com/xzhencheng/Sincere.Core

最近又要离职了。心情比较复杂!可能更新不及时。还望海涵!

以上是 .netCore+Vue 搭建的简捷开发框架 (5) 的全部内容, 来源链接: utcz.com/z/374748.html

回到顶部