未通过Container在构造函数中设置的属性

时间:2013-01-24 17:45:36

标签: c# dependency-injection servicestack funq

我使用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. 如果不是设计,那么发生了什么?

2 个答案:

答案 0 :(得分:4)

修改:

我已经确定这绝不是所希望的行为所以我只是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());

答案 1 :(得分:1)

我们的devteam的一些成员花了一些时间调试类似的问题。

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

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

我们的团队成员同意,当成员不是注册为Container.RegisterAs&lt;&gt;的类型时,很有可能将此成员设置为null。

我们正在使用ServiceStack版本4.0.33