我有以下配置:
For<ITranslatorProvider>().Singleton().Use<TranslatorProviderA>();
我有3个翻译提供者:TranslatorProviderA,B和C.
每个应该在某些名称空间下使用。
Project.Services&gt;使用提供商A
Project.Site&gt;用户提供商B
...
我可以根据请求来自哪个命名空间注入提供者A,B或C吗?
这可能吗?
答案 0 :(得分:1)
您应该可以使用a convention来完成此操作。这样的事情应该有效:
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中的built in conventions。
您可以在扫描中使用约定:
ObjectFactory.Initialize(c => c.Scan(s =>
{
s.TheCallingAssembly();
s.Convention<TranslationConvention>();
})
);
答案 1 :(得分:0)
我认为你不能根据命名空间注入提供者。但是你可以通过使用命名实例来实现同样的目标(如果我理解你的实现):
For<ITranslatorProvider>().Add<TranslatorProviderA>().Named("NS1");
For<ITranslatorProvider>().Add<TranslatorProviderB>().Named("NS2");
然后使用:
container.GetInstance<ITranslatorProvider>("NS1");