首页 > 解决方案 > Autofac 如何替换已注册的服务?

问题描述

我想写一个AOP框架(为了学习),我需要替换已经注册在Autofac中的服务。

Microsoft.Extensions.DependencyInjection中:</p>

        public static IServiceCollection BuildAopProxy(this IServiceCollection service)
        {
            if (service is null)
                throw new ArgumentNullException(nameof(service));

            IServiceCollection proxyServiceCollection = new ServiceCollection();

            foreach (ServiceDescriptor item in service)
            {
                Type newType;
                Type serviceType = item.ServiceType;
                Type implementationType = item.ImplementationType;

                if (serviceType == implementationType)
                {
                    newType = DynamicProxy.CreateProxyClassType(item.ImplementationType, true);
                }
                else
                {
                    newType = DynamicProxy.CreateProxyClassType(item.ServiceType, item.ImplementationType, false);
                }
                proxyServiceCollection.Add(ServiceDescriptor.Describe(serviceType, newType, item.Lifetime));
            }
            return proxyServiceCollection;
        }

这在 Autofac 中是如何工作的?谢谢你。

标签: dependency-injectionautofac

解决方案


这都是关于注册顺序的。文档中有一个部分。

基本上:最后获胜。

首先,重要的是要注意您在示例中使用的是 Microsoft.Extensions.DependencyInjection 库。这些都不是Autofac。Autofac可以与之集成但您设置注册的IServiceCollection方式不是 Autofac。

然而,最后获胜的概念适用于 Microsoft DI 以及 Autofac ......以及几乎所有其他 DI 容器。

如果我注册三个实现相同接口的东西......

svcCollection.AddTransient<IDependency, First>();
svcCollection.AddTransient<IDependency, Second>();
svcCollection.AddTransient<IDependency, Third>();

如果你解决了IDependency,你会得到Third

var provider = svcCollection.BuildServiceProvider();
var dependency = provider.GetService<IDependency>();
// dependency.GetType() == typeof(Third)

如果您真的想在这里使用 Autofac,则需要使用 Autofac.Extensions.DependencyInjection 将所有注册信息放入 Autofac。

var builder = new ContainerBuilder();
builder.Populate(svcCollection);
var container = builder.Build();

var dependency = container.Resolve<IDependency>();
// dependency.GetType() == typeof(Third)

或者您可以直接切换到使用本机 Autofac 注册。

var builder = new ContainerBuilder();
builder.RegisterType<First>().As<IDependency>();
builder.RegisterType<Second>().As<IDependency>();
builder.RegisterType<Third>().As<IDependency>();
var container = builder.Build();

var dependency = container.Resolve<IDependency>();
// dependency.GetType() == typeof(Third)

您正在做的部分似乎是试图将一些组件包装在装饰器或代理中。如果您使用本机 Autofac,则内置对装饰器类型拦截器的支持,这可能会让您的生活更轻松。标准 Microsoft DI 库不提供装饰器和拦截器。


推荐阅读