[英]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.