我有以下配置:
For<ITranslatorProvider>().Singleton().Use<TranslatorProviderA>();
我有 3 个翻译提供商:TranslatorProviderA、B 和 C。
每一个都应该在特定的命名空间下使用。
Project.Services > 使用提供者 A
Project.Site > 用户提供者 B
...
我可以根据请求来自哪个命名空间来注入提供者 A、B 或 C 吗?
这可能吗?
我有以下配置:
For<ITranslatorProvider>().Singleton().Use<TranslatorProviderA>();
我有 3 个翻译提供商:TranslatorProviderA、B 和 C。
每一个都应该在特定的命名空间下使用。
Project.Services > 使用提供者 A
Project.Site > 用户提供者 B
...
我可以根据请求来自哪个命名空间来注入提供者 A、B 或 C 吗?
这可能吗?
您应该能够使用约定来做到这一点。像这样的东西应该可以工作:
using System;
using System.Linq;
using StructureMap.Configuration.DSL;
using StructureMap.Graph;
using StructureMap.TypeRules;
class TranslationConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if(!type.IsConcrete())
return;
var ctor = Constructor.GetGreediestConstructor(type);
var translatorParameters= ctor.GetParameters()
.Where(p => typeof(ITranslatorProvider)
.IsAssignableFrom(p.ParameterType));
if(!translatorParameters.Any())
return;
Type translatorType = GetTranslatorType(type);
translationParameters.Aggregate(registry.For(type).Use(type),
(current, parameter) =>
current.CtorDependency<ITranslatorProvider>(parameter.Name)
.IsConcreteType(translatorType));
}
Type GetTranslatorType(Type type)
{
if(type.Namespace == "Project.Services")
return typeof(TranslatorProviderA);
if(type.Namespace == "Project.Site")
return typeof(TranslatorProviderB);
return typeof(TranslatorProviderC);
}
}
上面的约定仅适用于注册具体类型,因此如果您希望约定将类绑定到某个接口,您需要更改这部分:registry.For(type).Use(type)
变得更合适。查看StructureMap 中的内置约定以获取一些想法。
您可以在扫描中使用约定:
ObjectFactory.Initialize(c => c.Scan(s =>
{
s.TheCallingAssembly();
s.Convention<TranslationConvention>();
})
);
我不认为你可以基于命名空间注入提供者。但是你可以通过使用命名实例来实现同样的事情(如果我理解你的实现):
For<ITranslatorProvider>().Add<TranslatorProviderA>().Named("NS1");
For<ITranslatorProvider>().Add<TranslatorProviderB>().Named("NS2");
然后使用:
container.GetInstance<ITranslatorProvider>("NS1");