Как Autofa c заменяет зарегистрированную услугу? - PullRequest
0 голосов
/ 16 июня 2020

Я хочу написать фреймворк АОП (для изучения) , Мне нужно заменить сервис, который уже зарегистрирован в Autofa c.

В Microsoft.Extensions.DependencyInjection

        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;
        }

Как это работает в Autofa c? Спасибо.

1 Ответ

3 голосов
/ 17 июня 2020

Все дело в порядке регистрации. В документации по нему есть раздел.

В основном: Последний по победам.

Во-первых, важно отметить, что вы в вашем примере используется библиотека Microsoft.Extensions.DependencyInjection. Ничего из этого не является Autofa c. Autofa c может интегрировать с этим , но способ, которым вы настраиваете свои регистрации с помощью IServiceCollection, отличается от Autofa c.

Однако концепция last in wins применима как для Microsoft DI, так и для Autofa c ... и почти всех остальных контейнеров 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)

Если вы действительно хотите использовать здесь Autofa c, вам нужно поместите все регистрации в Autofa c с помощью Autofa c .Extensions.DependencyInjection.

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

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

Или вы можете напрямую переключиться на использование собственных регистраций Autofa c.

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)

Похоже, часть того, что вы делаете, пытается обернуть некоторые компоненты в декораторы или прокси. Если вы используете собственный Autofa c, в встроена поддержка декораторов и типа перехватчиков , которые могут облегчить вам жизнь. Декораторы и перехватчики не предлагаются стандартными библиотеками Microsoft DI.

...