问题描述
在各种Stack Overflow问题和博客文章之间,有一个非常合理的关于泛型和StructureMap主题的文档。不幸的是,我一直在想尝试使用 scan
执行配置以及一个具有贪心构造函数的类实现尚未工作的错误。 我希望StructureMap通过引用其实现的接口来抓取下面一个类的实例。 ToCsvService
存在于称为基础架构的未引用的程序集中。 IToCsvService
存在于名为Core的引用程序集中。你可以看到
ToCsvService
有一个贪心的构造函数。
public class ToCsvService< TSource> :IToCsvService< TSource>
{
public ToCsvService(ICollection< TSource>集合)
{
}
}
我通过 ConnectImplementationsToTypesClosing
方法让StructureMap了解 ToCsvService
/ p>
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly(Infrastructure);
scan.WithDefaultConventions();
//即使使用此调用StructureMap也不能使用ToCsvService
// IToCsvService的实例(尽管不会期望)
scan.ConnectImplementationsToTypesClosing
(typeof(IToCsvService));
});
});
从 ObjectFactory.WhatDoIHave()
方法看起来StructureMap知道 ToCsvService
。
PluginType名称描述
------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ---------------------------------
IToCsvService`1(IToCsvService`1)
作用为:Transient
6202a7ee-89a4-4edd-831d-4867b7dd1a7e 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 Infrastructure.Services.ToCsvService`1,Infrastructure,Version = 1.0.0.0的配置实例,Culture = neutral,PublicKeyToken = null
但是当我指定 IToCsvService&Cus tomerViewModel>
在Controller构造函数中抛出异常
我想,这是因为StructureMap不知道该怎么办贪心 ToCsvService
构造函数。有没有什么可以使StructureMap能够使用这个构造函数玩得很好?我需要从构造函数中切换,并在实例化之后设置collection属性?
问题细节有些我试图做,但不利用扫描来做到这一点。 由使用 For(x).Use(y)
配置,如果我不是扫描程序集,因为我没有参考 ToCsvService
。
编辑 br />
我想看看是否使用不同的机制让StructureMap识别 ToCsvService
会有一个效果。它会更改 ObjectFactory.WhatDoIHave()
中报告的内容,并引发不同的异常。以下是使用 AddAllTypesOf
的示例。
ObjectFactory.Initialize(cfg = >
{
cfg.Scan(scan =>
{
scan.Assembly(Infrastructure);
scan.WithDefaultConventions();
scan.AddAllTypesOf(typeof(IToCsvService));
});
});
从 ObjectFactory.WhatDoIHave()
是
PluginType名称说明
---------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -
IToCsvService`1(IToCsvService`1)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
的实例实例作为:Transient
Infrastructure.Services.ToCsvService`1,基础设施,版本= 1.0.0.0,Culture = neutral,PublicKeyToken = null Infrastructure.Services.ToCsvService`1,Infrastructure,Version = 1.0.0.0的配置实例,Culture = neutral,PublicKeyToken = null
----- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------
IToCsvService`1(IToCsvService`1)Infrastructure.Services.ToCsvService`1,基础设施,Vers ion = 1.0.0.0,Culture = neutral,PublicKeyToken = null Infrastructure.Services.ToCsvService`1,Infrastructure,Version = 1.0.0.0的配置实例,Culture = neutral,PublicKeyToken = null
作用为:Transient
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
使用此配置,我抛出此异常:
对我来说,异常表示StructureMap知道需要一个 ICollection< MachineForm>
来实例化 ToCsvService
但不知道从哪里得到它。来自以下关于使用StructureMap和评论structmap / ConstructorAndSetterInjection.htm#section3rel =noreferrer>构造方法setter注入。但是,如果没有添加对基础架构程序集的明确引用,这似乎是不可能的。
在StructureMap&泛型
关于StructureMap&泛型
是否有具体的IToCsvService实现?或者只是打开类型ToCsvService?
ConnectImplementationsToTypesClosing用于将具体的CustomerViewModelToCsvService类似于连接到IToCsvService<>。如果要连接打开的类来打开接口,您需要:
For(typeof(IToCsvService))) 。使用(typeof运算(ToCsvService<>));
这里我将打开的接口类型连接到打开的类类型。
Between various Stack Overflow questions and blog posts there is a pretty reasonable amount of documentation on the topic of open generics and StructureMap. Unfortunately, I must be missing something as my attempts at using scan
to perform the configuration along with a class implementation that has a "greedy" constructor have yet work.
I want StructureMap to grab an instance of the below class via references to its implemented interface. ToCsvService
exists in an unreferenced assembly called Infrastructure. IToCsvService
exists in a referenced assembly called Core. As you can seeToCsvService
has a "greedy" constructor.
public class ToCsvService<TSource> : IToCsvService<TSource>
{
public ToCsvService(ICollection<TSource> collection)
{
}
}
I let StructureMap know about ToCsvService
via the ConnectImplementationsToTypesClosing
method.
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<>));
});
});
From the ObjectFactory.WhatDoIHave()
method it appears that StructureMap is aware of 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
However when I specify IToCsvService<CustomerViewModel>
in a Controller constructor it throws the exception
I imagine that this is because StructureMap has no idea what to hand the "greedy" ToCsvService
constructor. Is there someway that I can make StructureMap able to play nice with this constructor? Do I need to switch from a constructor and just set the collection property after instantiation?
The question Structuremap and generic types details somewhat I am trying to do but does not utilize a scan to do so. The answer provided by Joshua Flanagan utilizes the For(x).Use(y)
configuration, which might work if I wasn't scanning the assembly because I don't have a reference ToCsvService
.
Edit
I wanted to see if using a different mechanism to let StructureMap identify instances of ToCsvService<>
would have an effect. It changes what's reported in ObjectFactory.WhatDoIHave()
and throws a different exception. Here's an example of using AddAllTypesOf
.
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly("Infrastructure");
scan.WithDefaultConventions();
scan.AddAllTypesOf(typeof(IToCsvService<>));
});
});
After using the above the dump from ObjectFactory.WhatDoIHave()
is
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
With this configuration I throw this exception:
To me the exception indicates that StructureMap knows it needs an ICollection<MachineForm>
to instantiate ToCsvService
but does not know where to get it from. Which goes to Jimmy's comment from below about using StructureMap and Constructor setter injection. However, this doesn't seem possible without adding an explicit reference to the Infrastructure assembly.
Somewhat related Stack Overflow questions on StructureMap & Generics
- Structuremap and generic types
- StructureMap setter injection in open generic type?
- StructureMap Auto registration for generic types using Scan
Blogs posts concerning StructureMap & Generics
- Advanced StructureMap: connecting implementations to open generic types
- Advanced StructureMap: custom registration conventions for partially closed types
- Open Generic Types in StructureMap
Are there any concrete implementations of IToCsvService? Or just the open type ToCsvService?
ConnectImplementationsToTypesClosing is for connecting something like a concrete CustomerViewModelToCsvService to IToCsvService<>. If you want to connect open classes to open interfaces, you'll need:
For(typeof(IToCsvService<>)).Use(typeof(ToCsvService<>));
Here I'm connecting the open interface type to the open class type.
这篇关于如何使用具有通用非闭合类型的StructureMap,使用“贪婪”构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!