如何使用Scan与“贪婪”构造函数一起使用StructureMap和通用非闭合类型

时间:2010-09-28 21:29:40

标签: c# asp.net-mvc generics dependency-injection structuremap

在各种Stack Overflow问题和博客文章之间,有关于开放式泛型和StructureMap主题的相当多的文档。不幸的是,我必须遗漏一些东西,因为我尝试使用scan执行配置以及具有“贪婪”构造函数的类实现仍然有效。

我希望StructureMap通过对其实现的接口的引用来获取下面的类的实例。 ToCsvService存在于名为Infrastructure的未引用程序集中。 IToCsvService存在于名为Core的引用程序集中。如你看到的 ToCsvService有一个“贪婪”的构造函数。

public class ToCsvService<TSource> : IToCsvService<TSource>
{
    public ToCsvService(ICollection<TSource> collection)
    {
    }
}

我通过ToCsvService方法让StructureMap了解ConnectImplementationsToTypesClosing

ObjectFactory.Initialize(cfg =>
{
    cfg.Scan(scan =>
    {
        scan.Assembly("Infrastructure");
        scan.WithDefaultConventions();

        // even with this call StructureMap cannot use ToCsvService
        // instance of IToCsvService (though wouldn't expect it to)
        scan.ConnectImplementationsToTypesClosing
            (typeof(IToCsvService<>));
    });
});

ObjectFactory.WhatDoIHave()方法看,StructureMap知道ToCsvService

PluginType                            Name                                                                                                            Description                                                                                                                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1)                                                                                                                                                                                                                                      
Scoped as:  Transient                                                                                                                                                                                                                                                                                  
                                      6202a7ee-89a4-4edd-831d-4867b7dd1a7e                                                                            Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
                                      Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                   

但是,当我在Controller构造函数中指定IToCsvService<CustomerViewModel>时,它会抛出异常

  

StructureMap异常代码:202   没有为PluginFamily Core.Services.IToCsvService`1 [[UI.Models.MachineForm,UI,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],Core,Version = 1.0.0.0,Culture = neutral定义默认实例,PublicKeyToken = null

我想这是因为StructureMap不知道如何处理“贪婪”ToCsvService构造函数。在某种程度上,我可以使StructureMap能够与这个构造函数一起玩吗?我是否需要从构造函数切换并在实例化后设置集合属性?

Structuremap and generic types这个问题在某种程度上是我试图做的,但没有利用扫描来做到这一点。 answer提供的Joshua Flanagan使用For(x).Use(y)配置,如果我没有扫描程序集,则可能会有效,因为我没有引用ToCsvService

修改

我想看看是否使用不同的机制让StructureMap识别ToCsvService<>的实例会产生影响。它会更改ObjectFactory.WhatDoIHave()中报告的内容并引发其他异常。以下是使用AddAllTypesOf

的示例
ObjectFactory.Initialize(cfg =>
{
    cfg.Scan(scan =>
    {
        scan.Assembly("Infrastructure");
        scan.WithDefaultConventions();

        scan.AddAllTypesOf(typeof(IToCsvService<>));
    });
});

使用上述内容后,ObjectFactory.WhatDoIHave()转储

PluginType                           Name                                                                                                                                 Description                                                                                                                                            
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1)    Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                        Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                   
Scoped as:  Transient

                                     Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                        Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                   
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IToCsvService`1 (IToCsvService`1)    Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                        Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                   
Scoped as:  Transient

                                     Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null                        Configured Instance of Infrastructure.Services.ToCsvService`1, Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

使用此配置,我抛出此异常:

  

StructureMap异常代码:202   没有为PluginFamily System.Collections.Generic.ICollection`1 [[UI.Models.MachineForm,UI,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]定义默认实例,mscorlib,版本= 4.0.0.0,文化=中立,PublicKeyToken = b77a5c561934e089

对我来说,异常表明StructureMap知道它需要ICollection<MachineForm>来实例化ToCsvService,但不知道从哪里获取它。关于使用StructureMap和Jimmy's,请参阅下面的Constructor setter injection评论。但是,如果不添加对基础结构程序集的显式引用,这似乎是不可能的。

关于StructureMap&amp ;;的一些相关的Stack Overflow问题。泛型

有关StructureMap&amp ;;的博客文章泛型

2 个答案:

答案 0 :(得分:10)

是否有任何具体的IToCsvService实现?或者只是打开类型ToCsvService?

ConnectImplementationsToTypesClosing用于将具体的CustomerViewModelToCsvService连接到IToCsvService&lt;&gt;。如果要将开放类连接到打开的接口,则需要:

For(typeof(IToCsvService<>)).Use(typeof(ToCsvService<>));

这里我将开放接口类型连接到开放类类型。

答案 1 :(得分:0)

实际上在当前版本中应该非常简单。您只需在调用以获取对象的新实例时提供参数。为此,您可以在objectfactory上使用“With”方法。

这允许您使用贪婪的构造函数。但是,这也意味着您必须知道在此示例中您需要该集合。因此,它不是注入状态的最佳方法。

var newObject = ObjectFactory.With<ICollection<CustomerViewModel>>(SomeCollection)
                .GetInstance<IToCsvService<CustomerViewModel>>();