我要建一个插件系统,电子商务项目,简单的注射器。我使用 RegisterAll
注册所有实施的 IPaymentProvider
A IResourceRegistrar (和在fure以上)。
I'm building a plugin system for an e-commerce project with Simple Injector. I'm using RegisterAll
to register all implementation of a IPaymentProvider
and of a IResourceRegistrar
(and in the fure more).
不过,这将创建一个新的实例每次。 这里是它建议使用 RegisterSingle
每种类型。但如何做到这一点在这种情况下?
But this creates a new instance each time. Here is it suggested to use RegisterSingle
on each type. But how to achieve this in this case?
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(类型)
不工作,从相同的接口固有的类型( IPaymentProvider
或 IResourceRegistrar
)。该 IPaymentProvider
实现类有构造不带参数的 IResourceRegistrar
用参数。
container.RegisterSingle(type)
does not work, as the types inherent from the same interface (IPaymentProvider
or IResourceRegistrar
). The IPaymentProvider
implementing classes have constructors without parameters, the IResourceRegistrar
with parameters.
我不想做这样的事情,它,而违背了一个IoC容器的目的
I don't want to do something like this, it rather defeats the purpose of a IoC container
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;
}
如何在不丑交换机注册这些作为单身?
How to register these as singleton without the ugly switch?
也许我误解,但RegisterSingle应该工作。你应该能够做到这一点:
Perhaps I misunderstand, but RegisterSingle should work. You should be able to do this:
var types = ...
container.RegisterAll<IInterface>(types);
foreach (var type in types)
{
container.RegisterSingle(type, type);
}
更新:
所以,你正在尝试做的是自动配置如下:
So what you are trying to do is to automate the following configuration:
// 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));
这通常是自动执行此方式。所以,做四个步骤:
This would typically be the way to automate this. So do four steps:
找到所有类型的注册。 在注册类型中作为单。 在注册类型为集合列表 I1
。
在注册类型为集合列表 I2
。
Find all types to register.
Register the found types as singleton.
Register the list of types as collection for I1
.
Register the list of types as collection for 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);
不过,因为你正试图分成两个步骤,创建一个可以处理每一步都有一个通用的方法,你将有当一个具体的单式已经注册忽略。您可以通过做到这一点:
However, since you are trying to split this into two steps and create one generic method that can handle each step, you will have to ignore when a concrete singleton type has already been registered. You can either do this by:
将捕获异常,从 RegisterSingle
抛出忽略登记。
通过设置覆盖现有注册 container.Options.AllowOverridingRegistrations = TRUE
之前调用 RegisterSingle
(之后禁用它会是最安全的)。
Ignoring the registration by catching the exception thrown from RegisterSingle
.
Override an existing registration by setting container.Options.AllowOverridingRegistrations = true
before calling RegisterSingle
(disabling it afterwards would be safest).