我可以在StructureMap中使用约定和实例名称吗?

时间:2013-05-06 19:36:10

标签: dependency-injection structuremap

当引导StructureMap时,我总是使用默认实例(而不是命名实例),并且能够定义一个简单的约定来按程序集扫描以连接实例。没有进入约定本身的细节,我会像这样引导:

assemblies.ForEach(a =>
    x.Scan(y =>
    {
        y.Assembly(a);
        y.WithDefaultConventions();
        y.Convention<DomainInterfaceNamingConvention>();
    }));

其中assemblies是我在初始化程序中放在其他地方的程序集列表,而DomainInterfaceNamingConvention是我自定义约定,用于扫描这些程序集以使接口与实现匹配。

只要我记得,这一点非常有效。但是,现在我有理由使用命名实例。因此,例如,我可以像这样引导我的记录器实现:

x.For<Logger>().Use(l => new Log4Net.LoggerImplementation());
x.For<Logger>().Add(l => new Log4Net.LoggerImplementation()).Named("Log4Net");
x.For<Logger>().Add(l => new NLog.LoggerImplementation()).Named("NLog");

因此定义了默认值,以及在代码专门请求一个时添加了一些命名实例。

但是,如何将两者合并?在我的命名实例示例中,配置是按类进行的,而在我的基于约定的实例示例中,配置是按装配进行的。我的一些程序集中有很多类,在这种特殊情况下,这些类可以相当频繁地来去。因此,需要手动连接每个类而不仅仅是每个程序集,这对于开发来说是一个非常微不足道的操作难题。

有没有办法在基于约定的扫描中在程序集级别拥有名称?因此,举例来说,我可能会为一个程序集提供大量名为“Database”的引导存储库实例,为另一个程序集提供一个名为“XML”的ton,以及另一个程序集中名为“Mock”的ton,而不必指定每个单独的存储库(在引导程序中,如果算上默认值,则为三次,四次?

1 个答案:

答案 0 :(得分:1)

我最终使用了一点点反思来实现这一目标。无论如何,偏爱约定优于配置,我的程序集名称都遵循类似的模式。因此,例如,我可能有三个实现DAL接口的程序集:

  • Acme.Infrastructure.DAL.SQLExpress
  • Acme.Infrastructure.DAL.XMLFiles
  • Acme.Infrastructure.DAL.Mock

这里的最终目标是,在程序集级别,我可以相应地配置命名实例。所以我可以这样做:

var fooRepository = IoCFactory.GetInstance<FooRepository>("SQLExpress");
var barRepository = IoCFactory.GetInstance<BarRepository>("XMLFiles");

无需为每个存储库(对于整个代码库中的每个接口/类组合)添加单独的配置行到引导代码,因为这对维护来说不直观,并且不能很好地扩展。

因此,在我的常规扫描程序中,我只获得在bootstrapping中使用的实现名称:

var implementationName = type.Assembly.GetName().Name.Split('.').Last();

然后,在其他逻辑中,将其添加到对象图中:

registry.For(interfaceType).Use(type).Named(implementationName);