代码之家  ›  专栏  ›  技术社区  ›  djdd87

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

  •  2
  • djdd87  · 技术社区  · 14 年前

    我试图避免以一个贫乏的域模型结束,所以我试图在域模型本身中保持尽可能多的逻辑。我有一个方法叫做 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 业务规则类。 是一个简单的命令处理程序,如下所示:

    public class GetIngredient : ICommandHandler<Ingredient, GetIngredientMessage>
    {
        private readonly IIngredientRepository _ingredientRepository;
    
        public GetIngredient(IIngredientRepository ingredientRepository)
        {
            _ingredientRepository = ingredientRepository;
        }
    }
    

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

     ServiceLocator.Factory = new IoCFactory();
    

    我很肯定我做错了什么,因为这一切都感觉有点像预兆。

    • 有人能看出什么明显的错误吗?
    • 有没有更合适的方法来实例化业务规则处理程序,例如 获取配料 没有对我的IoC工厂的静态引用?
    1 回复  |  直到 14 年前
        1
  •  3
  •   Szymon Pobiega    14 年前

    我建议您在设计中引入另一层--应用程序层。该层的职责是转换命令(或者显式封装在命令对象中,或者隐式传递为 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
            });
        }
    }
    

    希望有帮助。