我一直试图将泛型对象数组注入泛型类型的构造函数中,但找不到一种干净的方法。
我有一个像下面这样的课程:
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;
}
有人有更好/更干净的方法来实现这一点吗?我不喜欢在那里动态调用方法。