Как использовать StructureMap с общими незакрытыми типами, используя Scan с «жадным» конструктором - PullRequest
37 голосов
/ 29 сентября 2010

Между различными вопросами о переполнении стека и сообщениями в блогах имеется довольно много документации по теме открытых обобщений и StructureMap.К сожалению, я должен что-то упустить, так как мои попытки использовать scan для выполнения конфигурации вместе с реализацией класса, имеющей «жадный» конструктор, все еще работают.

Я хочу, чтобы StructureMap захватил экземплярниже класс через ссылки на его реализованный интерфейс.ToCsvService существует в несвязанной сборке, называемой инфраструктурой.IToCsvService существует в ссылочной сборке под названием Core.Как видите, ToCsvService имеет «жадный» конструктор.

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

Я сообщаю StructureMap о ToCsvService с помощью метода 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<>));
    });
});

Из *По методу 1015 * выясняется, что 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                   

Однако, когда я указываю IToCsvService<CustomerViewModel> в конструкторе контроллера, он выдает исключение

Код исключения StructureMap: 202 Экземпляр по умолчанию не определен для PluginFamily Core.Services.IToCsvService`1 [[UI.Models.MachineForm, UI, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = ноль]], ядро, версия = 1.0.0.0, культура= нейтральный, PublicKeyToken = null

Я предполагаю, что это потому, что StructureMap понятия не имеет, что передать «жадному» конструктору ToCsvService.Есть ли какой-то способ, которым я могу сделать StructureMap способным играть с этим конструктором?Нужно ли мне переключаться из конструктора и просто устанавливать свойство коллекции после создания экземпляра?

Вопрос Structuremap и универсальные типы детали, которые я пытаюсь сделать, но не использую сканирование, чтобы сделатьтак. ответ , предоставленный Джошуа Фланаган , использует конфигурацию 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, пользовательский интерфейс, версия = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]], mscorlib, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089

Для меня исключение указывает, что StructureMap знает, что ему требуется ICollection<MachineForm> для создания экземпляра ToCsvService, но не знает, куда обратитьсяполучить это от.Что касается комментария Джимми ниже об использовании StructureMap и Внедрение в конструктор .Однако это кажется невозможным без добавления явной ссылки на сборку инфраструктуры.

Несколько связанные с этим вопросы о переполнении стека в StructureMap & Generics

Сообщения блогов, касающиеся StructureMap & Generics

Ответы [ 2 ]

10 голосов
/ 29 сентября 2010

Существуют ли конкретные реализации IToCsvService? Или просто открытый тип ToCsvService?

ConnectImplementationsToTypesClosing предназначен для подключения чего-то вроде конкретного CustomerViewModelToCsvService к IToCsvService <>. Если вы хотите подключить открытые классы к открытым интерфейсам, вам потребуется:

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

Здесь я подключаю открытый тип интерфейса к открытому типу класса.

0 голосов
/ 14 марта 2014

На самом деле в текущей версии это должно быть очень просто.Все, что вам нужно сделать, это предоставить аргумент при вызове, чтобы получить новый экземпляр объекта.Для этого вы используете метод «С» на объекте фабрики.

Это позволяет вам использовать жадный конструктор.Однако это также означает, что вы должны знать, что вам нужна коллекция в этом примере.Так что это не оптимальный метод введения состояния.

var newObject = ObjectFactory.With<ICollection<CustomerViewModel>>(SomeCollection)
                .GetInstance<IToCsvService<CustomerViewModel>>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...