Зависимость конструктора массива с StructureMap - PullRequest
3 голосов
/ 01 ноября 2009

У меня есть некоторые ITask типы бетонов, определенные в моем TaskRegistry:

public class TaskResigstry : Registry
{
    public TaskResigstry()
    {
        ForRequestedType<IBootstrapperTask>().TheDefaultIsConcreteType<StartTasks>();

        ForRequestedType<ITask>().TheDefaultIsConcreteType<FirstTask>();
        ForRequestedType<ITask>().AddConcreteType<SecondTask>();
        ForRequestedType<ITask>().AddConcreteType<ThirdTask>();
    }
}

И мой StartTasks

public class StartTasks : IBootstrapperTask
{
    public StartTasks(ITask[] tasks)
    {
        foreach(var task in tasks)
        {
            task.Run();
        }
    }
}

Как я могу вставить параметр конструктора ITask[], используя StructureMap?

Спасибо.

Ответы [ 3 ]

3 голосов
/ 03 ноября 2009

Тебе больше ничего не нужно делать. Просто запросите экземпляр IBootstrapperTask, и все ITasks будут автоматически введены.

var container = new Container(x => x.AddRegistry<TaskResigstry>());
var bootstrapper = container.GetInstance<IBootstrapperTask>();

Примечание: StructureMap распознает массивы только для внедрения нескольких экземпляров - не измените конструктор так, чтобы он брал IEnumerable или строго типизированную коллекцию.

В качестве ярлыка, если вы хотите внедрить все экземпляры ITask в вашу сборку, без необходимости вручную регистрировать все из них, вы можете изменить свой реестр на:

public class TaskResigstry : Registry
{
    public TaskResigstry()
    {
        ForRequestedType<IBootstrapperTask>().TheDefaultIsConcreteType<StartTasks>();

        Scan(x =>
        {
            x.TheCallingAssembly();
            x.AddAllTypesOf<ITask>();
        });
    }
}
3 голосов
/ 03 ноября 2009

Если вы хотите добавить массив, есть метод для этого в свободном интерфейсе ...

ForRequestedType<IBootStrapperTask>().TheDefault.Is.OfConcreteType<StartTasks>()
     .TheArrayOf<ITask>().Contains(
            y => {
                y.OfConcreteType<Task1>();
                y.OfConcreteType<Task2>();
                y.OfConcreteType<Task3>();
            });

Если вы хотите пойти по пути принятия IEnumerable<T> в вашем конструкторе, насколько я вижу, все становится немного сложнее. Вы можете указать и построить аргумент конструктора следующим образом: -

ForRequestedType<IBootStrapperTask>().TheDefault.Is.OfConcreteType<StartTasks>()
            .CtorDependency<IEnumerable<ITask>>().Is(i => {
                i.Is.ConstructedBy(c => {
                    return new List<ITask> { 
                           c.GetInstance<Task1>(), 
                           c.GetInstance<Task2>(), 
                           c.GetInstance<Task3>()
                    };
                });
            });

Если вам нужны все зарегистрированные типы, вы можете создать собственный IBuildInterceptor, который обращается ко всем зарегистрированным типам через метод CreateInstanceArray в BuildSession, но у меня возникает ощущение, что я могу пойти по неправильному пути.

Я бы хотел, чтобы меня поправили, что это намного проще :).

1 голос
/ 10 марта 2013

Принятый ответ хорош, но синтаксис устарел. Вот новый синтаксис для того же:

this.For<IBootStrapperTask>().Use<StartTasks>()
    .EnumerableOf<ITask>().Contains(x =>
    {
        x.Type<Task1>();
        x.Type<Task2>();
        x.Type<Task3>();
    });

StructureMap великолепен, но меня часто расстраивает отсутствие примеров, использующих самый современный синтаксис.

...