在各种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评论。但是,如果不添加对基础结构程序集的显式引用,这似乎是不可能的。
答案 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>>();