这是从域模型中实例化具有依赖关系的对象的正确方法吗?

时间:2010-09-14 14:42:27

标签: c#-4.0 domain-driven-design inversion-of-control domain-data-modelling

我正在努力避免陷入贫血的域模型,所以我试图在域模型本身中保留尽可能多的逻辑。我有一个名为AddIngredient的方法,需要向我的KeyedObject聚合添加新的Recipe

由于域模型本身意味着没有存储库,我通过业务规则类获取该成分:

public class Recipe : AggregateObject
{
    public void AddIngredient(int ingId, double quantity)
    {
        GetIngredientMessage message = new GetIngredientMessage();
        message.IngredientId = ingId;

        GetIngredient handler = ServiceLocator.Factory.Resolve<GetIngredient>();
        Ingredient ingredient = handler.Execute(message);

        Ingredients.Add(new OriginalIngredient()
        {
            Ingredient = ingredient,
            Quantity = quantity
        });
    }
}

正如您所看到的,我正在使用第ServiceLocator.Factory.Resolve<GetIngredient>();行来获取我的GetIngredient业务规则类。 GetIngredient是一个简单的命令处理程序,如下所示:

public class GetIngredient : ICommandHandler<Ingredient, GetIngredientMessage>
{
    private readonly IIngredientRepository _ingredientRepository;

    public GetIngredient(IIngredientRepository ingredientRepository)
    {
        _ingredientRepository = ingredientRepository;
    }
}

我将IoC工厂类分配给ServiceLocator.Factory,因此Domain可以使用自己的接口,而无需查看具体的类实现:

 ServiceLocator.Factory = new IoCFactory();

我很确定我做错了什么,因为它感觉有点像波澜一样。

  • 有人能发现任何公然错误吗?
  • 是否有更合适的方法来实例化业务规则处理程序,例如GetIngredient而没有对IoC Factory的静态引用?

1 个答案:

答案 0 :(得分:3)

我建议你在设计中引入另一层 - 应用层。该层的职责是将命令(显式封装在命令对象中或隐式传递为int ingId, double quantity)转换为域模型调用(Recipe.AddIngredient)。

通过这样做,您将负责通过其ID查找成分到域上方的层,您可以安全地直接使用存储库而不会引入不需要的耦合。转换后的解决方案看起来像这样:

public class ApplicationLayer
{
   private readonly IRecipeRepository _recipeRepository;
   private readonly IIngredientRepository _ingredientRepository;

   /*
    * This would be called by IoC container when resolving Application layer class.
    * Repositories would be injected by interfacy so there would be no coupling to
    * concrete classes.
    */
   public ApplicationLayer(IRecipeRepository recipeRepository, IIngredientRepository ingredientRepository)
   {
      _recipeRepository = recipeRepository;
      _ingredientRepository = ingredientRepository;
   }

   public void AddIngredient(int recipeId, int ingId, double quantity)
   {
       var recipe = _recipeRepository.FindById(recipeId);
       var ingredient = _ingredientRepository.FindById(ingId);
       recipe.AddIngredient(ingredient, quantity);   
   }
}

现在简化的Recipe类看起来像这样:

public class Recipe : AggregateObject
{
    public void AddIngredient(Ingredient ingredient, double quantity)
    {
        Ingredients.Add(new OriginalIngredient()
        {
            Ingredient = ingredient,
            Quantity = quantity
        });
    }
}

希望有所帮助。