向autofac注册ImmutableArray

时间:2020-01-07 06:36:00

标签: c# autofac ioc-container

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

我想注册ImmutableArray<T>

我想要的语义与IEnumerable<T>相同-即Autofac应该创建一个ImmutableArray<T>的实例,并带有T的所有注册信息。

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

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

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

1 个答案:

答案 0 :(得分:0)

没有简单的方法来用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>();
相关问题