ASP.NET Core 的底层设计支持和使用依赖注入。ASP.NET Core
应用程序可以利用内置的框架服务将它们注入到启动类Startup的方法中,并且应用程序服务ConfigureServices能够配置注入。
依赖注入(Dependency injection,DI)是一种实现对象及其合作者或依赖项之间松散耦合的技术。
1、什么是依赖?
当一个类需要另一个类协作来完成工作的时候就产生了依赖。比如我们在AccountController这个控制器需要完成和用户相关的注册、登录 等事情。其中的登录我们由EF结合Idnetity来完成,所以我们封装了一个EFLoginService。这里AccountController就有一个ILoginService的依赖。
这里有一个设计原则:依赖于抽象,而不是具体的实现。所以我们给EFLoginService定义了一个接口,抽象了LoginService的行为。
2、什么是注入?
注入体现的是一个IOC(控制反转的的思想),把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。
private readonly IAccountAppService _accountAppService;
/// <summary>
/// 构造
/// </summary>
/// <param name="accountAppService">账户中心接口</param>
public AccountController(
IAccountAppService accountAppService
)
{
_accountAppService = accountAppService;
}
3、为什么要反转?
为了在业务变化的时候尽少改动代码可能造成的问题。
比如我们现在要把从EF中去验证登录改为从Redis去读,于是我们加了一个 RedisLoginService。这个时候我们只需要在原来注入的地方改一下就可以了。
// 用Redis来替换原来的EF登录 var controller = new AccountController(new RedisLoginService()); controller.Login(userName, password);
4、何为容器
上面我们在使用AccountController的时候,我们自己通过代码创建了一个IAccountServce的实例。想象一下,一个系统中如果有100个这样的地方,我们是不是要在100个地方做这样的事情? 控制是反转了,依赖的创建也移交到了外部。现在的问题是依赖太多,我们需要一个地方统一管理系统中所有的依赖,容器诞生了。
容器负责两件事情:
- 绑定服务与实例之间的关系
- 获取实例,并对实例进行管理(创建与销毁)
5、IOC容器的更换
1、首先得下载相应的NuGet包
Install-Package Autofac -Version 4.8.1
Install-Package Autofac.Extensions.DependencyInjection -Version 4.3.0
2、在ConfigureServices中创建容器对象,并返回IServiceProvider
#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);
this.ApplicationContainer = builder.Build();
return new AutofacServiceProvider(this.ApplicationContainer); //第三方IOC接管 core内置DI容器
//return services.BuilderInterceptableServiceProvider(builder => builder.SetDynamicProxyFactory());
#endregion
创建Runtime帮助获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
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 Dianshi.P2P.Core.Client.WebApi.Auth
{
[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;
});
}
}
}
ConfigureServices的返回值(默认为void)为IServiceProvider
运行
public ActionResult<string> Ioc()
{
return _accountAppService.Login(new Application.Members.Accounts.Dto.LoginInput() { Password = "1", Phone = "2" });
}
完成注入,欢迎评论,欢迎指正!