有没有一种干净的方法可以在Autofac中构建泛型类型参数?

时间:2020-09-11 13:55:13

标签: c# generics autofac

我一直试图将泛型对象数组注入泛型类型的构造函数中,但找不到一种干净的方法。

我有一个像下面这样的课程:

public sealed class RepositoryConsumer<T> : IRepositoryConsumer<T> Where T : BaseEntity
{
   private readonly IOtherDependency _otherDependency;
   private readonly IReadOnlyCollection<IRepository<T>> _regionalRepositories;

   public RepositoryConsumer<T>(
      IOtherDependency otherDependency,
      IReadOnlyCollection<IRepository<T>> regionalRepositories)
   {
      _otherDependency = otherDependency;
      _regionalRepositories = regionalRepositories;
   }
...

我需要手动配置IRepository<T>实例,因为它们将取决于应用程序中的其他因素。 (例如,某些区域由config驱动,T的类型仅对特定区域有效...等)

下面是我目前在Autofac模块中需要配置的注入方法,但是感觉应该有更好的方法。


private void BindRepositoryConsumers(ContainerBuilder builder)
        {
            builder.RegisterGeneric(typeof(IRepository<>)).As(typeof(IRepository<>));
            builder.RegisterGeneric(typeof(RepositoryConsumer<>))
                .As(typeof(IRepositoryConsumer<>))
                .WithParameter(
                    (parameter, context) => ParameterTypeIsReadonlyCollectionOfIRepositories(parameter),
                    (parameter, context) =>
                    {
                        var type = parameter.ParameterType.GenericTypeArguments.First().GenericTypeArguments.First();
                        return GetType()
                            .GetMethod(nameof(CreateRepositories))
                            .MakeGenericMethod(type)
                            .Invoke(this, BindingFlags.Default, null, new object[] { context }, CultureInfo.InvariantCulture);
                    }).SingleInstance();
        }

        private static bool ParameterTypeIsReadonlyCollectionOfRepositories(ParameterInfo parameter)
        {
            return parameter.ParameterType.IsGenericType &&
                   parameter.ParameterType.GetGenericArguments().First().IsGenericType &&
                   typeof(IReadOnlyCollection<>)
                       .MakeGenericType(typeof(IRepository<>).MakeGenericType(parameter.ParameterType.GenericTypeArguments.First().GenericTypeArguments.First()))
                       .IsAssignableFrom(parameter.ParameterType);
        }

        public static IReadOnlyCollection<IRepository<T>> CreateRepositories<T>(IComponentContext context) where T : BaseEntity
        {
            var repositoryProvider = context.Resolve<IRepositoryProvider>();
            var config = context.Resolve<IConfig>();

            var regionalRepositories = config.Regions.Select(region => repositoryProvider.Create<T>(region));

            return regionalRepositories;
        }

有人有更好/更干净的方法来实现这一点吗?我不喜欢在那里动态调用方法。

0 个答案:

没有答案