只有在使用Unity的运行时值为非空时,如何注入属性?

时间:2010-08-10 01:56:56

标签: c# .net dependency-injection unity-container

我有一个要解析的接口,其中一个映射对象的依赖项上有一个属性,我想设置一个值,当我解析顶级对象时,我只能使用它。

该属性没有有效的默认值。如果未设置,则它应为null,并且只有在解析时可用的值不为空时才应设置它。

这种条件属性注入是否可行?

我试过了......

container.RegisterType<ProductInstanceValidatorBase, CartItemPurchaseTypeValidator>("CartItemPurchaseTypeValidator", new InjectionProperty("AccountEntity", null);

...但它说我不能使用空值!

我也在解决问题上尝试了这个......

container.Resolve<ProductInstanceValidatorBase>(new PropertyOverride("AccountEntity", value));

...但是当值为null时抛出异常。它说,

  

参数类型推断不适用于空值。使用正确配置的InjectionParameter或InjectionParameter类实例显式指示参数类型。   参数名称:parameterValue

基本上我想要注册一个仅使用覆盖设置的属性,然后才会覆盖覆盖值为非null。有任何想法吗?当然,从语义的角度来看,属性注入应该是可选的。

干杯,伊恩。

3 个答案:

答案 0 :(得分:5)

此问题的一个可能解决方法是在您没有有效帐户时实施Null Object Pattern并传递Account.Empty。这是课程的样子:

public class Account {
   public static readonly Account Empty = new Account();
}

//at resolution time
Account account = null;
if (HasAccount) 
  account = GetAccount();
else 
  account = Account.Empty;

container.Resolve<ProductInstanceValidatorBase>(new PropertyOverride("AccountEntity", account));

这样,帐户永远不会null,实体框架也不会抱怨。

但是我觉得你的系统设计可能会遇到更大的问题。 IoC容器允许更松散耦合的系统,其中组件的布线在> 程序运行之前定义,而不是运行。从名称来看,AccountEnyity是一个实体类,而不是一个服务类,你通常用IoC容器注册实体,只注册服务。

鉴于上述情况,我建议AccountEntity不应该是注射财产,而是普通财产。然后,您将ProductInstanceValidatorBase创建外部化为工厂,并让它负责设置AccountEntity属性

public interface IProductInstanceValidatorFactory{
  ProductInstanceValidatorBase Create(Account account);
}
public class ProductInstanceValidatorFactory : IProductInstanceValidatorFactory{
  public ProductInstanceValidatorBase Create(Account account){
     var validator = new ProductInstanceValidator();
     validator.AccountEnity = account;
     return validator;
  }
}

您甚至不需要向Unity注册ProductInstanceValidatorBase,而是注册工厂。这就是使用工厂的样子:

Account account = null;
container.Resolve<IProductInstanceValidatorFactory>().Create(account);

答案 1 :(得分:4)

您可以将InjectionParameter与空值一起使用,但必须指定类型。 对于您的两个场景,我假设您的AccountEntity参数属于类型或派生自IAccount:

container.RegisterType<ProductInstanceValidatorBase, CartItemPurchaseTypeValidator>("CartItemPurchaseTypeValidator", new InjectionProperty<IAccount>(null);

请注意,我删除了名称,因为在上面的场景中并不是特别需要,但下面的场景需要它。

container.Resolve<ProductInstanceValidatorBase>(new PropertyOverride("AccountEntity", new InjectionProperty<IAccount>(null)));

答案 2 :(得分:-1)

我倾向于同意伊戈尔。但是,如果您绝对必须解析Entity,为什么不将您的IoC容器作为构造函数依赖项,然后尝试在构造函数中Resolve