如何使用具有通用非闭合类型的StructureMap,使用“贪婪”构造函数 [英] How do I use StructureMap with generic unclosed types using Scan with a "greedy" constructor

查看:313
本文介绍了如何使用具有通用非闭合类型的StructureMap,使用“贪婪”构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在各种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异常代码: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能够使用这个构造函数玩得很好?我需要从构造函数中切换,并在实例化之后设置collection属性?



问题结构图和通用类型细节有些我试图做,但不利用扫描来做到这一点。 answer Joshua Flanagan 使用 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异常代码:202
否为PluginFamily定义的默认实例System.Collections.Generic.ICollection`1 [[UI.Models.MachineForm,UI,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null]],mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089




对我来说,异常表示StructureMap知道需要一个 ICollection< MachineForm> 来实例化 ToCsvService 但不知道从哪里得到它。来自以下关于使用StructureMap和 Jimmy的评论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 see ToCsvService 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

StructureMap Exception Code: 202 No Default Instance defined for 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

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:

StructureMap Exception Code: 202 No Default Instance defined for PluginFamily System.Collections.Generic.ICollection`1[[UI.Models.MachineForm, UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

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

Blogs posts concerning StructureMap & Generics

解决方案

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,使用“贪婪”构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆