使用 autofac 注册 ImmutableArray

Register ImmutableArray with autofac

Autofac 允许您使用 RegisterGeneric 方法注册泛型类型。

我想报名ImmutableArray<T>

我想要的语义与 IEnumerable<T> 相同 - 即 Autofac 应该创建一个 ImmutableArray<T> 的实例,其中包含 T.[=16 的所有注册=]

如果这不是通用的,那就很简单了:

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

但是我看不到泛型类型的任何方法。

没有简单的方法可以用 lambda 表达式注册泛型方法。您需要使用具有泛型类型操作的 IRegistrationSource 来做到这一点。

类似的东西:

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>();