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

Ian*_*ton 1 .net c# dependency-injection unity-container

我有一个要解析的接口,其中一个映射对象的依赖项有一个属性,我想设置一个值,我只有在解析顶级对象时才可用.

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

这种有条件的财产注入可能吗?

我试过这个......

container.RegisterType<ProductInstanceValidatorBase, CartItemPurchaseTypeValidator>("CartItemPurchaseTypeValidator", new InjectionProperty("AccountEntity", null);
Run Code Online (Sandbox Code Playgroud)

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

我也试过这个决心......

container.Resolve<ProductInstanceValidatorBase>(new PropertyOverride("AccountEntity", value));
Run Code Online (Sandbox Code Playgroud)

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

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

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

干杯,伊恩.

Igo*_*aka 5

解决此问题的一个可能方法是实现Null对象模式,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));
Run Code Online (Sandbox Code Playgroud)

这样帐户永远不会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;
  }
}
Run Code Online (Sandbox Code Playgroud)

您甚至不需要在ProductInstanceValidatorBaseUnity 注册,而是注册工厂.这是使用工厂的样子:

Account account = null;
container.Resolve<IProductInstanceValidatorFactory>().Create(account);
Run Code Online (Sandbox Code Playgroud)