
正文
NetCore+Dapper WebApi架构搭建(四):仓储的依赖注入
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
上一节我们讲到实体,仓储接口和仓储接口的实现需要遵循约定的命名规范,不仅是规范,而且为了依赖注入,现在我们实现仓储的依赖注入
在NetCore WebApi项目中新添加一个文件夹(Unit),当然你也可以直接放在根目录下面,关键是后期类增加了你会找对地方,看起来不是那么乱,添加一个RuntimeHelper
我先说一下实现仓储依赖注入的基本思路,就是通过反射获取所有的程序集,然后在程序集中找到 I+实体+Repository的接口和 实体+Repository的实现类,然后在依赖注入容器中注册他们的对应关系
所以这个RuntimeHelper很明显是通过反射获取程序集使用的
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader; namespace Dinner.WebApi.Unit
{
[ApiExplorerSettings(IgnoreApi=true)]
public class RuntimeHelper
{
/// <summary>
/// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
/// </summary>
/// <returns></returns>
public static IList<Assembly> GetAllAssemblies()
{
List<Assembly> list = new List<Assembly>();
var deps = DependencyContext.Default;
//排除所有的系统程序集、Nuget下载包
var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");
foreach (var lib in libs)
{
try
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
list.Add(assembly);
}
catch (Exception ex)
{
//
}
}
return list;
} public static Assembly GetAssembly(string assemblyName)
{
return GetAllAssemblies().FirstOrDefault(f => f.FullName.Contains(assemblyName));
} public static IList<Type> GetAllTypes()
{
List<Type> list = new List<Type>();
foreach (var assembly in GetAllAssemblies())
{
var typeinfos = assembly.DefinedTypes;
foreach (var typeinfo in typeinfos)
{
list.Add(typeinfo.AsType());
}
}
return list;
} /// <summary>
/// 根据AssemblyName获取所有的类
/// </summary>
/// <param name="assemblyName"></param>
/// <returns></returns>
public static IList<Type> GetTypesByAssembly(string assemblyName)
{
List<Type> list = new List<Type>();
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
var typeinfos = assembly.DefinedTypes;
foreach (var typeinfo in typeinfos)
{
list.Add(typeinfo.AsType());
}
return list;
} public static Type GetImplementType(string typeName, Type baseInterfaceType)
{
return GetAllTypes().FirstOrDefault(t =>
{
if (t.Name == typeName && t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
{
var typeinfo = t.GetTypeInfo();
return typeinfo.IsClass && !typeinfo.IsAbstract && !typeinfo.IsGenericType;
}
return false;
});
}
}
}
上面的那个[ApiExplorerSettings(IgnoreApi=true)]是使用Swagger时使用的,这个我们后面会讲
上面的类就是是反射对程序集的操作
这个我们要使用第三方的Autofac依赖注入框架,所以先引入Nuget包:Autofac.Configuration和Autofac.Extensions.DependencyInjection
下面打开startUp.cs类
先把ConfigureServices方法的返回值由void变为IServiceProvider
然后在ConfigureServices的AddMvc()之后添加下面代码
#region 依赖注入
var builder = new ContainerBuilder();//实例化容器
//注册所有模块module
builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
//获取所有的程序集
//var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
var assemblys = RuntimeHelper.GetAllAssemblies().ToArray();
//注册所有继承IDependency接口的类
builder.RegisterAssemblyTypes().Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);
//注册仓储,所有IRepository接口到Repository的映射
builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();
//注册服务,所有IApplicationService到ApplicationService的映射
//builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("AppService") && !t.Name.StartsWith("I")).AsImplementedInterfaces();
builder.Populate(services);
ApplicationContainer = builder.Build();
return new AutofacServiceProvider(ApplicationContainer); //第三方IOC接管 core内置DI容器
//return services.BuilderInterceptableServiceProvider(builder => builder.SetDynamicProxyFactory());
#endregion
这样以来注入就可以了
现在添加一个UsersController进行测试
using Dinner.Dapper.Entities;
using Dinner.Dapper.IRepository;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks; namespace Dinner.WebApi.Controllers
{ [Route("api/[controller]/[action]")]
public class UsersController : Controller
{
private readonly IUserRepository userRepository;
public UsersController(IUserRepository _userRepository)
{
userRepository = _userRepository;
} /// <summary>
/// 获取所有用户
/// </summary>
/// <returns></returns>
///
[HttpGet]
public async Task<JsonResult> GetUsers()
{
List<Users> list = await userRepository.GetUsers();
return Json(list);
} /// <summary>
/// 新增用户
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
[HttpPost]
public async Task PostUser(Users entity)
{
entity.Password = Dapper.Helpers.Encrypt.Md5(entity.Password).ToUpper();
await userRepository.PostUser(entity);
} /// <summary>
/// 修改用户信息
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
[HttpPut]
public async Task PutUser(Users entity)
{
try
{
entity.Password = Dapper.Helpers.Encrypt.Md5(entity.Password).ToUpper();
await userRepository.PutUser(entity);
}
catch (Exception ex)
{
throw new ArgumentException(ex.Message);
}
} /// <summary>
/// 删除用户
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
[HttpDelete]
public async Task DeleteUser(Guid Id)
{
try
{
await userRepository.DeleteUser(Id);
}
catch (Exception ex)
{
throw new ArgumentException(ex.Message);
}
}
}
}
自己测试一下仓储的增删改查吧,看看写的有问题没有
下一节我们讲解Swagger构建WebApi界面
赠送一个Framework版本的依赖注入
#region autofac IOC容器配置
var builder = new ContainerBuilder(); //注册所有的controller
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
//注册所有模块module
builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray(); //注册所有继承IDependency接口的类
builder.RegisterAssemblyTypes(assemblys)
.Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract); //注册服务,所有IxxxxRepository=>xxxxRepository
builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces(); var container = builder.Build(); BaseInfo._container = container; DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
#endregion
源码地址: https://github.com/wangyulong0505/Dinner






