2

我正在使用 Simple Injector 为电子商务项目构建一个插件系统。我用来注册 a和 a 的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;
}

如何在没有丑陋开关的情况下将这些注册为单例?

4

1 回答 1

2

也许我误解了,但是 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.
  • container.Options.AllowOverridingRegistrations = true在调用之前通过设置覆盖现有注册RegisterSingle(之后禁用它是最安全的)。
于 2012-12-03T19:14:01.893 回答