Fork me on GitHub

NetCore+Dapper WebApi架构搭建(四):仓储的依赖注入

上一节我们讲到实体,仓储接口和仓储接口的实现需要遵循约定的命名规范,不仅是规范,而且为了依赖注入,现在我们实现仓储的依赖注入

在NetCore WebApi项目中新添加一个文件夹(Unit),当然你也可以直接放在根目录下面,关键是后期类增加了你会找对地方,看起来不是那么乱,添加一个RuntimeHelper

我先说一下实现仓储依赖注入的基本思路,就是通过反射获取所有的程序集,然后在程序集中找到 I+实体+Repository的接口和 实体+Repository的实现类,然后在依赖注入容器中注册他们的对应关系

所以这个RuntimeHelper很明显是通过反射获取程序集使用的

 1 using Microsoft.AspNetCore.Mvc;
 2 using Microsoft.Extensions.DependencyModel;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Reflection;
 7 using System.Runtime.Loader;
 8 
 9 namespace Dinner.WebApi.Unit
10 {
11     [ApiExplorerSettings(IgnoreApi=true)]
12     public class RuntimeHelper
13     {
14         /// <summary>
15         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
16         /// </summary>
17         /// <returns></returns>
18         public static IList<Assembly> GetAllAssemblies()
19         {
20             List<Assembly> list = new List<Assembly>();
21             var deps = DependencyContext.Default;
22             //排除所有的系统程序集、Nuget下载包
23             var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");
24             foreach (var lib in libs)
25             {
26                 try
27                 {
28                     var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
29                     list.Add(assembly);
30                 }
31                 catch (Exception ex)
32                 {
33                     //
34                 }
35             }
36             return list;
37         }
38 
39         public static Assembly GetAssembly(string assemblyName)
40         {
41             return GetAllAssemblies().FirstOrDefault(f => f.FullName.Contains(assemblyName));
42         }
43 
44         public static IList<Type> GetAllTypes()
45         {
46             List<Type> list = new List<Type>();
47             foreach (var assembly in GetAllAssemblies())
48             {
49                 var typeinfos = assembly.DefinedTypes;
50                 foreach (var typeinfo in typeinfos)
51                 {
52                     list.Add(typeinfo.AsType());
53                 }
54             }
55             return list;
56         }
57 
58         /// <summary>
59         /// 根据AssemblyName获取所有的类
60         /// </summary>
61         /// <param name="assemblyName"></param>
62         /// <returns></returns>
63         public static IList<Type> GetTypesByAssembly(string assemblyName)
64         {
65             List<Type> list = new List<Type>();
66             var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
67             var typeinfos = assembly.DefinedTypes;
68             foreach (var typeinfo in typeinfos)
69             {
70                 list.Add(typeinfo.AsType());
71             }
72             return list;
73         }
74 
75         public static Type GetImplementType(string typeName, Type baseInterfaceType)
76         {
77             return GetAllTypes().FirstOrDefault(t =>
78             {
79                 if (t.Name == typeName && t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
80                 {
81                     var typeinfo = t.GetTypeInfo();
82                     return typeinfo.IsClass && !typeinfo.IsAbstract && !typeinfo.IsGenericType;
83                 }
84                 return false;
85             });
86         }
87     }
88 }
View Code

上面的那个[ApiExplorerSettings(IgnoreApi=true)]是使用Swagger时使用的,这个我们后面会讲

上面的类就是是反射对程序集的操作

这个我们要使用第三方的Autofac依赖注入框架,所以先引入Nuget包:Autofac.Configuration和Autofac.Extensions.DependencyInjection

下面打开startUp.cs类

先把ConfigureServices方法的返回值由void变为IServiceProvider

然后在ConfigureServices的AddMvc()之后添加下面代码

 1 #region 依赖注入
 2 
 3             var builder = new ContainerBuilder();//实例化容器
 4             //注册所有模块module
 5             builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
 6             //获取所有的程序集
 7             //var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
 8             var assemblys = RuntimeHelper.GetAllAssemblies().ToArray();
 9 
10             //注册所有继承IDependency接口的类
11             builder.RegisterAssemblyTypes().Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);
12             //注册仓储,所有IRepository接口到Repository的映射
13             builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();
14             //注册服务,所有IApplicationService到ApplicationService的映射
15             //builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("AppService") && !t.Name.StartsWith("I")).AsImplementedInterfaces();
16             builder.Populate(services);
17             ApplicationContainer = builder.Build();
18 
19             return new AutofacServiceProvider(ApplicationContainer); //第三方IOC接管 core内置DI容器 
20             //return services.BuilderInterceptableServiceProvider(builder => builder.SetDynamicProxyFactory());
21             #endregion
View Code

这样以来注入就可以了

现在添加一个UsersController进行测试

 1 using Dinner.Dapper.Entities;
 2 using Dinner.Dapper.IRepository;
 3 using Microsoft.AspNetCore.Mvc;
 4 using System;
 5 using System.Collections.Generic;
 6 using System.Threading.Tasks;
 7 
 8 namespace Dinner.WebApi.Controllers
 9 {
10 
11     [Route("api/[controller]/[action]")]
12     public class UsersController : Controller
13     {
14         private readonly IUserRepository userRepository;
15         public UsersController(IUserRepository _userRepository)
16         {
17             userRepository = _userRepository;
18         }
19 
20         /// <summary>
21         /// 获取所有用户
22         /// </summary>
23         /// <returns></returns>
24         /// 
25         [HttpGet]
26         public async Task<JsonResult> GetUsers()
27         {
28             List<Users> list = await userRepository.GetUsers();
29             return Json(list);
30         }
31 
32         /// <summary>
33         /// 新增用户
34         /// </summary>
35         /// <param name="entity"></param>
36         /// <returns></returns>
37         [HttpPost]
38         public async Task PostUser(Users entity)
39         {
40             entity.Password = Dapper.Helpers.Encrypt.Md5(entity.Password).ToUpper();
41             await userRepository.PostUser(entity);
42         }
43 
44         /// <summary>
45         /// 修改用户信息
46         /// </summary>
47         /// <param name="entity"></param>
48         /// <returns></returns>
49         [HttpPut]
50         public async Task PutUser(Users entity)
51         {
52             try
53             {
54                 entity.Password = Dapper.Helpers.Encrypt.Md5(entity.Password).ToUpper();
55                 await userRepository.PutUser(entity);
56             }
57             catch (Exception ex)
58             {
59                 throw new ArgumentException(ex.Message);
60             }
61         }
62 
63         /// <summary>
64         /// 删除用户
65         /// </summary>
66         /// <param name="Id"></param>
67         /// <returns></returns>
68         [HttpDelete]
69         public async Task DeleteUser(Guid Id)
70         {
71             try
72             {
73                 await userRepository.DeleteUser(Id);
74             }
75             catch (Exception ex)
76             {
77                 throw new ArgumentException(ex.Message);
78             }
79         }
80     }
81 }
View Code

自己测试一下仓储的增删改查吧,看看写的有问题没有

下一节我们讲解Swagger构建WebApi界面

赠送一个Framework版本的依赖注入

 1 #region autofac IOC容器配置
 2             var builder = new ContainerBuilder();
 3 
 4             //注册所有的controller
 5             builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
 6             //注册所有模块module
 7             builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
 8 
 9             var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
10 
11             //注册所有继承IDependency接口的类
12             builder.RegisterAssemblyTypes(assemblys)
13             .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);
14 
15             //注册服务,所有IxxxxRepository=>xxxxRepository
16             builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();
17           
18             var container = builder.Build();
19 
20             BaseInfo._container = container;
21 
22             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
23             #endregion
View Code

 

源码地址: https://github.com/wangyulong0505/Dinner

posted @ 2018-04-27 10:51  雪山玉龙  阅读(6859)  评论(2编辑  收藏  举报