Зарегистрируйте ImmutableArray с помощью autofac - PullRequest
1 голос
/ 07 января 2020

Autofa c позволяет регистрировать генерические типы c с помощью метода RegisterGeneri c.

Я хочу зарегистрировать ImmutableArray<T>.

Семантика, которую я хочу так же, как и для IEnumerable<T>, а именно Autofac должен создать экземпляр ImmutableArray<T> со всеми регистрациями T.

Если бы это был не универсальный c, это было бы просто:

builder.Register<ImmutableArray<string>>(c => c.Resolve<IEnumerable<string>>().ToImmutableArray());

Однако я не вижу никакого пути к этому с универсальными c типами.

1 Ответ

0 голосов
/ 10 января 2020

Нет простого способа зарегистрировать обобщенный метод c с лямбда-выражением. Для этого вам нужно использовать IRegistrationSource с типовой манипуляцией c.

Примерно так:

public class ImmutableArrayRegistrationSource : IRegistrationSource
{
    public bool IsAdapterForIndividualComponents => false;

    private static MethodInfo toImmutableArrayMethod =
            typeof(ImmutableArray)
                .GetMethods()
                .Where(m => m.Name == nameof(ImmutableArray.ToImmutableArray)
                            && m.GetParameters().Any(p => p.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
                .FirstOrDefault();

    public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        IServiceWithType typedService = service as IServiceWithType;

        if (typedService != null && typedService.ServiceType.IsClosedTypeOf(typeof(ImmutableArray<>)))
        {
            Type elementType = typedService.ServiceType.GetGenericArguments()[0];

            IComponentRegistration r = RegistrationBuilder.ForDelegate(typedService.ServiceType, (c, p) =>
            {
                Object elements = c.Resolve(typeof(IEnumerable<>).MakeGenericType(elementType));
                Object immutableArray = toImmutableArrayMethod.MakeGenericMethod(elementType)
                                                              .Invoke(null, new Object[] { elements });

                return immutableArray;
            }).As(service)
              .CreateRegistration();

            yield return r;
        }
        yield break;
    }
}

и затем зарегистрируйте свой источник регистрации:

builder.RegisterSource<ImmutableArrayRegistrationSource>();
...