Autofac整合.NET5 Mvc
1.指定Autofac工厂替换默认工厂,Program指定
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(new AutofacServiceProviderFactory());
2.在Startup类增加Configurecontainer方法,注册关系
/// <summary>
/// 整个方法被Autofa自动调用
/// 负责注册各种服务。尽管Autofac有专门的地方来注册服务
///之前ServiceColleetion注册的服务其实也会生效;
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>();
containerBuilder.RegisterType<TestServiceB>().As<ITestServiceB>();
containerBuilder.RegisterType<TestServiceC>().As<ITestServiceC>().PropertiesAutowired();
}
第二种方式
#region ServiceCollection注册的服务可以让Autofac使用,因为Autofac在自己注册服务之前;会先把ScrviceCollection中注册的服务全部接管过来;
services.AddTransient<ITestServiceA, TestServiceA>();
services.AddTransient<ITestServiceB, TestServiceB>();
services.AddTransient<ITestServiceC, TestServiceC>();
#endregion
2.通过控制器构造的数注入,获取实例
public class TestServiceCController : Controller
{
private readonly ITestServiceA _testServiceA;
private readonly ITestServiceC _testServiceC;
private readonly ITestServiceB _testServiceB;
public TestServiceCController(
ITestServiceA testServiceA,
ITestServiceC testServiceC,
ITestServiceB testServiceB
)
{
_testServiceA=testServiceA;
_testServiceC=testServiceC;
_testServiceB= testServiceB;
}
public IActionResult Index()
{
_testServiceC.show();
return View();
}
}
Autofac支持控制器属性注入
控制器是一个类,控制器的实例其实是IControllerActivator来创建的;
1. 得让控制器使用容器来获取实例(Startup.cs);
public void ConfigureServices(IServiceCollection services)
{
#region 指定控制器实例让容器来创建
services.Replace(ServiceDescriptor.Transient<IControllerActivator,ServiceBasedControllerActivator>());
#endregion
}
2. 注册控制器抽象和具休的关系(Startup.cs)
/// <summary>
/// 整个方法被Autofa自动调用
/// 负责注册各种服务
/// </summary>
/// <param name="containerBuilder"></param>
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
// 这样注册不够; 控制器的创建还需要依赖于其他的任何内容; 既然要注册就需要把所有依赖的内容都注册进来;
//containerBuilder.RegisterType<TestServiceCController>().As<ControllerBase>();
#region 注册所有控制器的关系 控制器实例化需要的所有组件
Type[] controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(new CustomPropertySelector());
#endregion
3. 在控制器内定义属性
public class TestServiceCController : Controller
{
[CustomPropertyAttribute]
private ITestServiceA TestServiceA { get; set; }
private ITestServiceA TestServiceB { get; set; }
private ITestServiceA TestServiceC { get; set; }
private readonly ITestServiceA _testServiceA;
private readonly ITestServiceC _testServiceC;
private readonly ITestServiceB _testServiceB;
public TestServiceCController(
ITestServiceA testServiceA,
ITestServiceC testServiceC,
ITestServiceB testServiceB
)
{
_testServiceA=testServiceA;
_testServiceC=testServiceC;
_testServiceB= testServiceB;
}
public IActionResult Index()
{
_testServiceC.show();
return View();
}
}
4. 扩展,自己控制究竟哪些属性需要做依赖注入
CustomPropertyAttribute.cs
[AttributeUsage(AttributeTargets.Property)]
public class CustomPropertyAttribute:Attribute
{
}
CustomPropertySelector
public class CustomPropertySelector : IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
//需要一个判断的范围
return propertyInfo.CustomAttributes.Any(it => it.AttributeType== typeof(CustomPropertyAttribute));
}
}
Autofac抽象多实现的问题
1.一个抽象多个实例,都注册了,通过构造函数用抽象类型来获取实例,哪个后面注册就获取到哪一个;覆盖型;
2.一个抽象多个实例,都注册了,可以通过一个IEnumerables<抽象>,当做构造函数参数,可以获取到所有注册的具体的实例;
3.注朋一个抽象的多个实例资源
startup.cs
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
#region 注册所有控制器的关系 控制器实例化需要的所有组件
Type[] controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
containerBuilder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired(new CustomPropertySelector());
#endregion
#region 注册单抽象多实例
containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>();
containerBuilder.RegisterType<TestServiceUpdate>().As<ITestServiceA>();
#endregion
#region 单抽像多实现
containerBuilder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t =>
t.IsAssignableTo<ITestServiceA>()));
#endregion
}
TestServiceCController
private readonly ITestServiceA _testServiceA;
private readonly IEnumerable<ITestServiceA> _testServiceAList;
private readonly TestServiceA _testServiceA1112;
private readonly TestServiceUpdate _testServiceUpdate;
public TestServiceCController(
ITestServiceA testServiceA,
IEnumerable<ITestServiceA> testServiceAList,
TestServiceA testServiceA1112,//接受具体的
TestServiceUpdate testServiceUpdate//接受具体的
)
{
_testServiceA = testServiceA;
testServiceAList = _testServiceAList;
testServiceA1112 = _testServiceA1112;
testServiceUpdate = _testServiceUpdate;
}
Autofac支持AOP
AOP面向切面编程;不用修改之前代码的基础上,可以动态的在某个动作之前加一些操作,动态在在某一个动作之后做点什么事儿。
1.Nuget引入Castle.Core程序集+Autofac.Extras.DynamicProxy程序集合
2.在服务的抽象上标记[Intercept(typeof(CustomAutofacAop))]
[Intercept(typeof(CustomAutofacAop))] //AOP能够在当前接口生效
public interface ITestServiceA
{
void show();
}
3.注册支持AOP扩展的类
containerBuilder.RegisterType(typeof(CustomAutofacAop));
4.注册服务的时候,需要调用EnableInterfaceInterceptors, 标记说明当前服务获取实例后可以支持AOP
#region Autofac支持AOP
containerBuilder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t =>
t.IsAssignableTo<ITestServiceA>()));
containerBuilder.RegisterType(typeof(CustomAutofacAop));
containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>()
.EnableInterfaceInterceptors();//接口
containerBuilder.RegisterType<TestServiceUpdate>().As<ITestServiceA>()
.EnableInterfaceInterceptors();// 接口
#endregion
public class CustomAutofacAop : IInterceptor
{
public void Intercept(IInvocation invocation)
{
{
Console.WriteLine("方法执行前");
}
invocation.Proceed();//执行这句话就是去执行具体的实例的这个方法
{
Console.WriteLine("方法执行后");
}
}
}
Autofac支持AOP-2
EnableInterfaceInterceptors+抽象标记特性[Interceptypeof(CustomAutofacAop),只要是实现了这个抽象就可以支持AOP
EnableClassInterceptors +实现类标记特性(Interceptitypeof(CustomAutofacop)] ,只有标记了这个特性的,才能够支持AOP
如果使用EnableClassInterceptors来支持AOP,实现类中支持AOP的方法必须为虚方法;
containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>()
.EnableClassInterceptors();