Datas-project 和 Builders-project 之间的循环依赖

Cyclic dependency between Datas-project and Builders-project

这里是我想要实现的代码:

  • A Character has strength, constitution, and some other stats.
  • Each Character has BaseStats depending of his class.
  • Each Character has RandomStats bonus, with positive values from 0 to 3.
  • A stat may not be lower than 1, nor higher than 10.
  • A Character may have Bonus and Malus in their stats.
  • If a Character has 8 in strength, plus a bonus of 4, and a malus of 1, he finally has 10 (8+4-1=11 > 10).
  • If a Character has 3 in constitution, plus a bonus of 1, and a malus of 4, he finally has 1 (3+1-4=0 < 1).

在我的 .NET 解决方案中,我尝试将 datasbuilders 分开放在不同的项目中。目前,我的 datas 项目中有这样的东西:

namespace Data.Entities.Characters
{
    public abstract class Character : Entity
    {
        public abstract EntityStats BaseStats { get; }
        public EntityStats RandomStats { get; }
    }
}

namespace Data.Stats
{
    public struct EntityStats
    {
        private Dictionary<EntityStat, int> _stats;
        public int this[EntityStat stat] { get { return _stats[stat]; } }

        public EntityStats(int strength, int constitution, /* ... */)
        {
            _stats = new Dictionary<EntityStat, int>();
            _stats.Add(EntityStat.Strength, strength);
            _stats.Add(EntityStat.Constitution, constitution);
            /* ... */
        }
    }
}

然后,我有一个 builderList<EntityStats

namespace Builder
{
    public class EntityStatsBuilder
    {
        private List<EntityStats> StatsList { get; set; }
        public EntityStatsBuilder() { StatsList = new List<EntityStats>(); }
        public void Add(EntityStats stats) { StatsList.Add(stats); }

        public EntityStats ToStats()
        {
            int strength = 0,
                constitution = 0, 
                /* ... */;

            foreach (EntityStats stats in StatsList)
            {
                strength += stats[EntityStat.Strength];
                constitution += stats[EntityStat.Constitution];
                /* ... */
            }

            // module FMath =
            //     let Clamp value min max =
            //         if value < min then min elif value > max then max else value
            return new EntityStats(
                FMath.Clamp(strength, 1, 10),
                FMath.Clamp(constitution, 1, 10),
                /* ... */
            );
        }
    }
}

我的问题如下:

My builders project references my datas project.
ERROR: I want to add a FinalStats property in my Character class. This FinalStats should use my EntityStatsBuilder class. Then, my datas project should reference my builders project.

public EntityStats FinalStats
{
    get
    {
        EntityStatsBuilder builder = new EntityStatsBuilder();
        builder.Add(BaseStats);
        builder.Add(RandomStats);
        return builder.ToStats();
    }
}

我应该如何修改我的全局架构才能避免这种循环依赖?

你要找的就是所谓的依赖倒置原则https://en.wikipedia.org/wiki/Dependency_inversion_principle

基本上为您的 EntityStatsBuilder 创建一个界面并将其放在一个单独的项目中。 现在两个项目都可以引用该接口项目。如果要遵循 Microsoft 命名约定,请将其命名为 SomethingSomething.Abstractions.

现在,在使用依赖项注入的启动项目中,您在 Character 对象中注入了一个具体的 EntityStatsBuilder。为此,您可以根据需要使用 DI 框架或简单的构造函数注入。