[英]Registering multiple named types using reflection in Autofac
我大约有100个存储库类,它们都实现相同的接口。 它们都有共同的依赖性。
我已经用不同的名称注册了这个通用依赖的两个版本。
我想使用命名的依赖项第二次注册我所有的存储库类。
这基本上是我的原始注册的样子:
builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IClientContext),
(pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Published)))
.AsImplementedInterfaces();
因此,如果我想使用不同的密钥第二次注册所有相同的类型,则需要执行以下操作:
builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IClientContext),
(pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Unpublished)))
.Named(RegistrationKeys.Unpublished)
.AsImplementedInterfaces();
但是,这将不起作用,因为Named方法要求指定注册的类型,但是它应该基于RegisterAssemblyTypes调用中的一系列解析类型而为动态的。
如何在不向应用程序中添加数百行代码的情况下做到这一点?
您可能可以编写自己的扩展方法来完成此操作。
您可能已经注意到 .Named
的重载 .Named
一个函数:
builder.RegisterAssemblyTypes(typeof(AComponent).GetTypeInfo().Assembly)
.Named(t => t.Name, typeof(object));
该函数接受从程序集中注册的Type
,并使用该Type在服务上生成名称。 不幸的是,该重载也仅将特定的固定类型用作服务类型,因此这会将所有内容注册为Named<object>(...)
,这不是您想要的。
但!
如果您看一下它是如何实现的 ...
public static IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
Named<TLimit, TScanningActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration,
Func<Type, string> serviceNameMapping,
Type serviceType)
where TScanningActivatorData : ScanningActivatorData
{
return registration.As(t => new KeyedService(serviceNameMapping(t), serviceType));
}
...您可以看到基本上是将类型注册,然后将其传递给您提供的函数以生成该名称。 您可以将其更改为不采用特定的服务类型,而仅将其注册为自己。
public static IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
NamedSelf<TLimit, TScanningActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration,
Func<Type, string> serviceNameMapping)
where TScanningActivatorData : ScanningActivatorData
{
return registration.As(t => new KeyedService(serviceNameMapping(t), t));
}
现在使用您的自定义NamedSelf
扩展名。
builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IClientContext),
(pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Unpublished)))
.NamedSelf(t => RegistrationKeys.Unpublished)
.AsImplementedInterfaces();
当然,您可以根据需要进行更新。 也许您不希望它成为一个函数,而只是接受一个字符串-很简单。 也许您希望将其注册为命名接口-您可以让函数生成整个KeyedService
而不是将其嵌入扩展名中。
要点是,您可以使用现有扩展名作为灵感来编写自己的自定义扩展名,这些自定义扩展名可以满足您的需求,而不必手动注册。
[免责声明:除了我的头脑之外, 我没有通过编译器来运行所有这些操作,因此可能会有错别字使复制/粘贴停止编译。 您还需要检查null参数和所有其他内容。 单击链接以查看实际的原始资源。 希望这至少可以解除您的封锁。]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.