使用StructureMap的数组构造函数依赖项

3

我在我的TaskRegistry中定义了一些ITask的具体类型:

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();
        }
    }
}

我该如何使用StructureMap注入ITask[]构造函数参数?
谢谢。
3个回答

3
如果您想注入一个数组,在流畅接口中有一个方法可以做到这一点...
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,在BuildSession的CreateInstanceArray方法中访问所有已注册的类型,但我感觉可能走了一条错误的路。我很乐意得到更正:) 。

2
如果你想使用IEnumerable<T>,但不想指定每个实例,可以像这样做:.CtorDependency<IEnumerable<ITask>>().Is(instance => instance .ConstructedBy(ctx => ctx.GetInstance<IContainer>().GetAllInstances<ITask>())); - Joshua Flanagan
我以为我走错了路。忘记了我可以进入容器,干杯! - John Foster

3

您无需进行其他操作,只需请求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>();
        });
    }
}

1

被接受的答案不错,但语法已经过时。下面是新的语法来实现相同的功能:

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

StructureMap很棒,但我经常因缺乏使用最新语法的示例而感到沮丧。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接