【问题标题】:Array Constructor Dependency With StructureMapStructureMap 的数组构造函数依赖关系
【发布时间】:2018-01-31 04:15:04
【问题描述】:

我的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[] 构造函数参数?

谢谢。

【问题讨论】:

    标签: c# dependency-injection structuremap


    【解决方案1】:

    如果你想注入一个数组,在流畅的界面中有一个方法......

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

    如果您想在构造函数中接受IEnumerable&lt;T&gt; 的路线,据我所知,事情开始变得有点复杂。您可以像这样指定和构建构造函数参数:-

    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 方法访问所有注册的类型,但我觉得我可能会走错路。

    我很想得到纠正,这更容易:)。

    【讨论】:

    • 如果你想使用 IEnumerable,但又不想指定每个实例,你可以这样做:.CtorDependency>().Is(instance = > instance .ConstructedBy(ctx => ctx.GetInstance().GetAllInstances()));
    • 我以为我走错了路。忘了我可以到达容器,干杯!
    【解决方案2】:

    您无需再做任何事情。只需请求一个 IBootstrapperTask 实例,所有 ITask 都会自动注入。

    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】:

      接受的答案很好,但语法已过时。这是执行相同操作的新语法:

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

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

      【讨论】:

        猜你喜欢
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        • 2013-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多