【问题标题】:Property not being set in constructor by Container容器未在构造函数中设置属性
【发布时间】:2013-01-24 17:45:35
【问题描述】:

我有一个使用ServiceStack 创建的服务。我将 Funq 用于我的依赖注入,因为它默认附带 ServiceStack,但这可能是其他 DI 容器表现出的行为。

我在启动时注册我的类型:

this.AppContainer.RegisterAs<ConcreteDownloadServices, IDownloadServices>();`

我在一个类中有这个构造函数:

private readonly IDownloadServices downloadServices;

public ExampleService(IDownloadServices downloadServices)
{
    this.downloadServices = downloadServices;
}

而我的具体实现的构造函数是:

public ConcreteDownloadServices()
{
    this.ArbitraryProperty = "ArbitraryString";
}

一切都解决得很好,我可以进入代码并查看事情是否按预期工作。但是,AbritraryProperty 没有正确设置。我可以单步执行并看到它设置为字符串值,但是一旦代码返回到调用代码(在此示例中,它将是 ExampleService 的构造函数)ArbitraryProperty 现在为 null。

  1. 这是设计使然吗?
  2. 如果是设计使然,那么使用 DI 是否意味着我不应该在具体实现的构造函数中做任何事情?
  3. 如果是设计使然,为自动属性设置默认值的正确方法是什么?
  4. 如果不是设计使然,那是怎么回事?

【问题讨论】:

    标签: c# dependency-injection servicestack funq


    【解决方案1】:

    编辑:

    我已经决定这不是我们想要的行为,所以我只是 checked in a commit 来强制 Funq 不会自动装配字符串(和 ValueType)属性。新行为将在下一个版本的 ServiceStack (v3.9.34) 中提供。

    现有行为

    RegisterAs 是一个 Autowired API,即:

    Container.RegisterAs<ConcreteDownloadServices, IDownloadServices>();
    

    这告诉 ServiceStack 的 IOC 使用 IOC 解决的依赖项填充每个公共属性。因为它是 string 公共属性,所以将尝试从 IOC 解析注册的 string。用代码术语来说,这是在幕后发生的:

    new ConcreteDownloadServices { 
        ArbitraryProperty = Container.TryResolve<string>()
    };
    

    因为您没有注册任何“字符串”,所以将使用null 覆盖该属性。只有公共属性是自动连接的,因此您可以通过将其更改为受保护的、私有的或内部属性来避免这种行为。

    否则,您可以通过注册一个自定义委托工厂来覆盖默认的 IOC 行为,这使您可以完全控制依赖项的构建,例如:

    container.Register<IDownloadServices>(c => new ConcreteDownloadServices());
    

    【讨论】:

    • 惊人的信息,感谢那个神话 :) 更改属性修饰符已被淘汰,因为它实现了一个接口,因此必须是一个公共属性。将 Register 与委托工厂一起使用看起来像是答案。但是,这是否表明如果我想使用 RegisterAs 或其他 Autowired API,我不应该使用值类型属性?对于我的特定场景,在接口中有一些东西来强制实现这个字符串对我来说是有意义的,但我只能使用公共属性来做到这一点(我认为!)。
    • 意味着添加 - 我想我需要创建一个接口和具体实现,其中包含我的依赖字符串并将其注入以使用 RegisterAs?
    • @thudbutt 认为这不是理想的行为,因此 Funq 将不再尝试在我将在周末发布到 NuGet 的下一个版本的 ServiceStack 中解析字符串属性。
    【解决方案2】:

    我们开发团队的一些成员刚刚花了一些时间调试一个类似的问题。

    在我们的一个单元测试中使用的 RegisterAs 类有一个公共成员: 公共列表邮件{获取;放; }

    当这个类通过 Funq 解析时,成员被设置为 null,即使它是在构造函数中设置的。

    我们的团队成员同意,当该成员不是注册为 Container.RegisterAs 的类型时,Funq 将此成员设置为 null 是很奇怪的。

    我们使用的是 ServiceStack 版本 4.0.33

    【讨论】:

      猜你喜欢
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 2015-12-08
      相关资源
      最近更新 更多