Array Constructor Dependency With StructureMap
I've some ITask
concretes types defines in my TaskRegistry
:
public class TaskResigstry : Registry
{
public TaskResigstry()
{
ForRequestedType<IBootstrapperTask>().TheDefaultIsConcreteType<StartTasks>();
ForRequestedType<ITask>().TheDefaultIsConcreteType<FirstTask>();
ForRequestedType<ITask>().AddConcreteType<Secon开发者_如何转开发dTask>();
ForRequestedType<ITask>().AddConcreteType<ThirdTask>();
}
}
And my StartTasks
public class StartTasks : IBootstrapperTask
{
public StartTasks(ITask[] tasks)
{
foreach(var task in tasks)
{
task.Run();
}
}
}
How can i inject the ITask[]
constructor parameter using StructureMap ?
Thanks.
If you want to inject an Array there's a method for that in the fluent interface...
ForRequestedType<IBootStrapperTask>().TheDefault.Is.OfConcreteType<StartTasks>()
.TheArrayOf<ITask>().Contains(
y => {
y.OfConcreteType<Task1>();
y.OfConcreteType<Task2>();
y.OfConcreteType<Task3>();
});
If you want to go down the route of an accepting an IEnumerable<T>
in your constructor as far as I can see things start to become a little more complicated. You can specify and build the constructor argument like so:-
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>()
};
});
});
If you want all the registered types you could make a custom IBuildInterceptor that accesses all the registered types via the CreateInstanceArray method on the BuildSession but I get the feeling I might be going down the wrong road there.
I'd love to be corrected that this is a lot easier :).
You don't have to do anything more. Just ask for an instance of IBootstrapperTask, and all of the ITasks will automatically be injected.
var container = new Container(x => x.AddRegistry<TaskResigstry>());
var bootstrapper = container.GetInstance<IBootstrapperTask>();
Note: StructureMap will only recognize arrays for injecting multiple instances - do not change the constructor to take an IEnumerable or strongly typed collection.
As a shortcut, if you want to inject all instances of ITask in your assembly, without having to manually register all of them, you can change your registry to:
public class TaskResigstry : Registry
{
public TaskResigstry()
{
ForRequestedType<IBootstrapperTask>().TheDefaultIsConcreteType<StartTasks>();
Scan(x =>
{
x.TheCallingAssembly();
x.AddAllTypesOf<ITask>();
});
}
}
The accepted answer is good, but the syntax is out of date. Here is the new syntax to do the same:
this.For<IBootStrapperTask>().Use<StartTasks>()
.EnumerableOf<ITask>().Contains(x =>
{
x.Type<Task1>();
x.Type<Task2>();
x.Type<Task3>();
});
StructureMap is great, but I am often frustrated by the lack of examples that use the most up-to-date syntax.
精彩评论