簡體   English   中英

多個 RegisterAll 注冊使用與 SimpleInjector 相同的一組單例

[英]Multiple RegisterAll registrations using the same set of singletons with SimpleInjector

我正在使用 Simple Injector 為電子商務項目構建插件系統。 我正在使用RegisterAll來注冊IPaymentProviderIResourceRegistrar (以及更多)的所有實現。

但這每次都會創建一個新實例。 這里建議在每種類型上使用RegisterSingle 但是在這種情況下如何實現這一目標?

private static void RegisterMultipleUnderOneInterface(
    Container container, string name)
{
    IEnumerable<Type> pluginRegistrations =
        from dll in finder.Assemblies
        from type in dll.GetExportedTypes()
        where type.GetInterfaces().Any(i => i.Name == name)
        where !type.IsAbstract
        where !type.IsGenericTypeDefinition
        select type;

    if (pluginRegistrations.Any())
    {
        var @interface =
            pluginRegistrations.ElementAt(0).GetInterfaces()
            .First(i => i.Name == name);

        foreach (Type type in pluginRegistrations)
        {
            // HERE: register the type single somehow. 
        }

        container.RegisterAll(@interface, pluginRegistrations);
    }
} 

container.RegisterSingle(type)不起作用,因為來自同一接口( IPaymentProviderIResourceRegistrar )的固有類型。 IPaymentProvider實現類具有不帶參數的構造函數, IResourceRegistrar具有參數。

我不想做這樣的事情,它反而違背了 IoC 容器的目的

var constructor = type.GetConstructors()[0];

switch (name)
{
    case "IResourceRegistrar":
        container.RegisterSingle(type, () =>
        {
            return constructor.Invoke(new object[
            {
                container.GetInstance<ILanguageService>()});
            });
        break;
    case "IPaymentProvider":
    default:
        container.RegisterSingle(type, () =>
        {
            return constructor.Invoke(new object[] { });
        });
        break;
}

如何在沒有丑陋開關的情況下將這些注冊為單例?

也許我誤解了,但 RegisterSingle 應該可以工作。 你應該能夠做到這一點:

var types = ...

container.RegisterAll<IInterface>(types);

foreach (var type in types)
{
    container.RegisterSingle(type, type);
}

更新:

所以你要做的是自動化以下配置:

// A, B, C and D implement both I1 and I2.
container.RegisterSingle<A>();
container.RegisterSingle<B>();
container.RegisterSingle<C>();
container.RegisterSingle<D>();

container.RegisterAll<I1>(typeof(A), typeof(B), typeof(C), typeof(D));
container.RegisterAll<I2>(typeof(A), typeof(B), typeof(C), typeof(D));

這通常是自動執行此操作的方法。 所以做四個步驟:

  1. 查找要注冊的所有類型。
  2. 將找到的類型注冊為單例。
  3. 將類型列表注冊為I1集合。
  4. 將類型列表注冊為I2集合。

這看起來像這樣:

// using SimpleInjector.Extensions;

Type[] singletons = FindAllTypesToRegister();

foreach (Type type in singletons)
{
    container.RegisterSingle(type, type);
}

container.RegisterAll(typeof(I1), singletons);
container.RegisterAll(typeof(I2), singletons);

但是,由於您試圖將其拆分為兩個步驟並創建一個可以處理每個步驟的通用方法,因此您將不得不忽略具體的單例類型已經注冊的情況。 您可以通過以下方式執行此操作:

  • 通過捕獲從RegisterSingle拋出的異常來忽略RegisterSingle
  • 在調用RegisterSingle之前通過設置container.Options.AllowOverridingRegistrations = true覆蓋現有RegisterSingle (之后禁用它是最安全的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM