【问题标题】:Castle Windsor IOC: Passing constructor parameters to child componentsCastle Windsor IOC:将构造函数参数传递给子组件
【发布时间】:2010-10-11 09:23:30
【问题描述】:

以下代码仅用于演示目的。

假设我有 2 个组件(businessService 和 dataService)和一个 UI 类。

UI类需要业务服务,businessService需要dataService,dataService依赖connectionString。

形成我需要解析业务服务的 UI 类,所以我正在编写以下代码:

var service = container.Resolve<BusinessService>(new { dependancy = "con string 123" }));

请注意,依赖是 connectionString 构造函数参数。

但是上面的代码不起作用,说 dataService 期望依赖不满足。

无法创建组件“dataService” 因为它有依赖关系 使满意。数据服务正在等待 以下依赖项:

键(具有特定键的组件) - 未注册的依赖关系。

所以作为一种解决方法,我正在这样做:

var service = container.Resolve<BusinessService>(new { dataService = container.Resolve<IDataService>(new { dependancy = "123" }) });

但从设计、编码风格和许多角度来看,这并不是一个好方法。

所以,如果您能告知为什么它不能以简单的方式工作,或者您有更好的解决方法,请分享。

【问题讨论】:

  • 您能否提供一个简短但完整的 BusinessService、DataService 和dependancy/connectionString 定义?删除任何不会直接导致重现问题的代码。
  • 公共类 BusinessService { public BusinessService(DataService dataService) {} }
  • public class DataService { public DataService(string dependency) {} }
  • 温莎动态参数:kozmic.net/2009/12/10/…

标签: .net castle-windsor


【解决方案1】:

您看到的行为是设计使然。

有几种方法可以解决这个问题,具体取决于您要传递的值的动态程度。

The documentation 详细说明了这一点,所以我不会在这里重复。

更新

为了清楚起见 - Windsor 不会将内联参数传递到解析管道。原因很简单——这样做会破坏抽象。调用代码必须隐式知道您的BusinessService 依赖于DataService,而DataService 又依赖于连接字符串。

如果您绝对必须这样做,请明确说明。这几乎就是你正在做的事情 - 显式解析 DataService 及其对连接字符串的依赖,并显式解析 BusinessService 并将 DataService 作为依赖传递。

为了让事情变得更加明确(并且更好地使用),我建议使用 Typed Factory 而不是直接调用容器

public interface IFactory
{
   IDataService ResolveDataService(string connectionString);
   IBussinessService ResolveBussinessService(IDataService dataService);
   // possibly release method for IBussinessService as well
}

【讨论】:

  • 检查了你的链接,但我真的不明白他们在说什么,我们能不能简单地回答一下
  • @moutasema 我的简单问题是,当我解决父组件-但-为其子组件发送参数时,这会起作用吗? @moutasema 容器可以自动将参数传递给子组件吗? @kkozmic 不,内联参数不会沿解析管道传播
  • @Moutasem al-awa:简而言之,您尝试做的事情在 99% 的情况下都是不好的做法。避免直接调用Resolve()(因为你是在做服务定位而不是依赖注入),你会看到正确的方法。
  • 您好,mauricio,您是否可以包含一个简单的示例?
  • 不错的捕获@Nate-Wilkins :) 已修复
【解决方案2】:

在创建需要上下文对象的瞬态组件时,我需要这样做。我使用的解决方案是覆盖 DefaultDependencyResolver 类,以便它确实将内联参数传递到解析管道。

public class ArgumentPassingDependencyResolver : DefaultDependencyResolver
{
    protected override CreationContext RebuildContextForParameter(
        CreationContext current, Type parameterType)
    {
        if (parameterType.ContainsGenericParameters)
        {
            // this behaviour copied from base class
            return current;
        }

        // the difference in the following line is that "true" is passed
        // instead of "false" as the third parameter
        return new CreationContext(parameterType, current, true);
    }
}

在创建容器时需要传入这个类的一个实例(其他类也需要传入,因为没有方便的构造函数只接受依赖解析器):

var container = new WindsorContainer(
    new DefaultKernel(
        new ArgumentPassingDependencyResolver(),
        new NotSupportedProxyFactory()),
    new DefaultComponentInstaller());

【讨论】:

    【解决方案3】:

    是的,您的请求是可能的,但您应该通过 Typed Factory Facility 使用抽象工厂,而不是直接通过容器请求您的服务。

    使用类型化工厂,您只需定义工厂接口,Windsor 将为您处理实现。

    public interface IBusinessServiceFactory {
      IBusinessService CreateBusinessService(string connString);
    }
    
    public interface IDataServiceFactory {
      IDataService CreateDataService(string connString);
    }
    

    您添加设施并注册您的工厂接口,如下所示:

    container.AddFacility<TypedFactoryFacility>();
    container.Register(Component.For<IDataServiceFactory>().AsFactory());
    container.Register(Component.For<IBusinessServiceFactory>().AsFactory());
    

    您现在可以通过在 BusinessServiceregistration 中定义 Dynamic Parameter 来手动定义运行时参数如何在对象图中传递。

    container.Register(Component.For<IBusinessService, BusinessService>()
        .LifestyleTransient()
        .DynamicParameters((k, d) => {
            d["dataService"] = k.Resolve<IDataServiceFactory>.CreateDataService((string)d["connString"]);
        }));
    

    请记住,字典键必须与 CreateBusinessService 方法和 BusinessService 构造函数中的参数名称匹配。

    如果您打算在每次调用工厂方法时创建一个新实例,您也应该将其设为LifestyleTransient。 (默认为单例)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      相关资源
      最近更新 更多