【问题标题】:How to Pass a Dependency to a Castle Windsor Typed Factory如何将依赖项传递给 Castle Windsor Typed Factory
【发布时间】:2025-12-26 17:10:17
【问题描述】:

我正在使用 Castle Windsor 3.3 并且有一个需要注入 IMachine 实例的 ViewModel。此数据在运行时才可用,因此我正在尝试使用 Typed Factory。

public MachDataViewModel(IMachine mach) 
{
        _mach = machCfg;
}

public interface IEquipmentDataFactory 
{
    IEquipmentData Create(IMachine mach);
    void Release(IMachine mach);
}

这是我的注册码:

container.AddFacility<TypedFactoryFacility>();
container.Register(
    Component.For<IWindsorContainer>().Instance(container),
    Component.For<IEquipmentData>().ImplementedBy<EquipmentData>(),
    Component.For<IMachine>().ImplementedBy<Machine>(),
    Component.For<IEquipmentDataFactory>().AsFactory());

当我调用 Create 方法时,它会注入一个新实例化的对象,而不是我传递的那个。如果我在我的注册中删除了Component.For&lt;IMachine&gt; 条目,它就会给我一个缺失的依赖关系。

IEquipmentData ed = null;
IMachine m = GetMachine();
ed = factory.Create(m);

如何让 Windsor 使用我传递给工厂的对象?

谢谢

【问题讨论】:

    标签: c# castle-windsor factory


    【解决方案1】:

    问题是使用TypedFactoryFacility Castle 知道如何为您解决IEquipmentData(可能)但是当它试图解决它的依赖项时它失败了,因为它们没有注册并且没有其他SubResolver如何解析IMachine的知识。

    使用以下类:(问题中的那些不编译)

    public class IMachine
    {
        public Guid Id { get; set; } = Guid.NewGuid();
    }
    
    public interface IEquipmentData { IMachine Machine { get; set; } }
    public class MachineDataViewModel : IEquipmentData
    {
        public IMachine Machine { get; set; }
        public MachineDataViewModel(IMachine machine) { Machine = machine; }
    }
    
    1. 选项 1 - 没有 TypedFactory:

      WindsorContainer container = new WindsorContainer();
      container.Register(
          Component.For<IEquipmentData>()
                   .ImplementedBy<MachineDataViewModel>()
                   .LifestyleTransient());
      
      var machine = new IMachine();
      var resultWithoutFactory = container.Resolve<IEquipmentData>(new Dictionary<string, object> { ["machine"] = machine });
      
    2. 选项 2 - 使用 TypedFactoryFacility。在这种情况下,您将必须实现 ITypedFactoryComponentSelector 来协助 Castle 并解释使用您传递的 IMachine 解析 IEquipmentData 的参数是什么。

      public interface IMachineFactory
      {
          IEquipmentData Create(IMachine machine);
      }
      
      public class EquipmentDataComponentSelector : ITypedFactoryComponentSelector
      {
          public Func<IKernelInternal, IReleasePolicy, object> SelectComponent(MethodInfo method, Type type, object[] arguments)
          {
              return (k, s) => k.Resolve<IEquipmentData>(new Dictionary<string, object> { ["machine"] = arguments[0] });
          }
      }
      

      主要:

      WindsorContainer container = new WindsorContainer();
      container.AddFacility<TypedFactoryFacility>();
      container.Register(
          Component.For<IEquipmentData>()
                   .ImplementedBy<MachineDataViewModel>()
                   .LifestyleTransient(),
          Component.For<EquipmentDataComponentSelector>(),
          Component.For<IMachineFactory>()
                   .AsFactory(f => f.SelectedWith<EquipmentDataComponentSelector>()));
      
      var machine = new IMachine();
      var factory = container.Resolve<IMachineFactory>();
      var resultWithFactory = factory.Create(machine);
      

    结果:(传递给容器/工厂的机器是IEquipmentData中的机器)

    【讨论】: