1

我有以下配置:

For<ITranslatorProvider>().Singleton().Use<TranslatorProviderA>();

我有 3 个翻译提供商:TranslatorProviderA、B 和 C。

每一个都应该在特定的命名空间下使用。

Project.Services > 使用提供者 A

Project.Site > 用户提供者 B

...

我可以根据请求来自哪个命名空间来注入提供者 A、B 或 C 吗?

这可能吗?

4

2 回答 2

1

您应该能够使用约定来做到这一点。像这样的东西应该可以工作:

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>();
    })
);
于 2013-03-27T08:47:00.113 回答
0

我不认为你可以基于命名空间注入提供者。但是你可以通过使用命名实例来实现同样的事情(如果我理解你的实现):

For<ITranslatorProvider>().Add<TranslatorProviderA>().Named("NS1");
For<ITranslatorProvider>().Add<TranslatorProviderB>().Named("NS2");

然后使用:

container.GetInstance<ITranslatorProvider>("NS1");
于 2013-03-25T23:03:59.217 回答