C# 项目中的工厂应该住在哪里?

C# 项目中的工厂应该住在哪里?,c#,domain-driven-design,factory-pattern,C#,Domain Driven Design,Factory Pattern,我有一个名为mudeengine.Core的项目解决方案。这个项目包含一些基本类,然后是我的域对象所抽象的所有接口。像IWorld和IRealm这样的接口 域接口示例 当我在IWorld接口上调用CreateRealm时,实现使用IRealmFactory来创建它。工厂是通过IWorld实现的构造函数传入的 我现在的问题是,工厂实施应该存在于哪里?对于包含域接口实现的同一个项目,为工厂提供实现是很常见的,还是消费层(如表示/单元测试项目)应该负责实现和使用工厂 其目的是,这些组件可以根据您正在构

我有一个名为
mudeengine.Core
的项目解决方案。这个项目包含一些基本类,然后是我的域对象所抽象的所有接口。像
IWorld
IRealm
这样的接口

域接口示例 当我在IWorld接口上调用
CreateRealm
时,实现使用IRealmFactory来创建它。工厂是通过IWorld实现的构造函数传入的

我现在的问题是,工厂实施应该存在于哪里?对于包含域接口实现的同一个项目,为工厂提供实现是很常见的,还是消费层(如表示/单元测试项目)应该负责实现和使用工厂

其目的是,这些组件可以根据您正在构建的基于文本的游戏类型进行交换。所以我倾向于每个实现接口的包都有自己的工厂。不过我关心的是DI设置。在分层(服务器/客户机应用程序)中更上层的IoC容器需要知道它应该使用每个包中的哪个工厂,而不是只使用IoC容器所属的消费层中定义的工厂


有任何行业标准的指导吗?

似乎您正在尝试用抽象的子域(我猜您可以称它们为子域,因为它们是成熟的游戏系统)构建域模型,即用户可以在运行时动态选择子域,从而触发一些子域不可知行为,然后在一段时间内使用它做特定于子域的事情,完成后可能会跳转到另一个子域

根据我的经验,在“正常”业务线项目中,您很少会遇到这种情况,但我会这样做:

  • 为通用世界和领域管理创建一个总体的有界上下文。将
    IWorld
    IRealmFactory
    放在那里

  • 为每个游戏系统子域创建单独的有界上下文。它们可以是整个项目,也可以只是名称空间。在这些中编写
    IRealmFactory
    的实现

  • 我认为这是使用
    Container.Resolve(…)
    的少数实例之一。在IoC配置中创建命名注册,并随时解析其中一个,以连接对应于一个游戏系统的对象子图


您似乎在尝试用抽象子域构建域模型(我想您可以称它们为子域,因为它们是成熟的游戏系统),即用户可以在运行时动态选择子域,从而触发一些子域不可知行为,然后在一段时间内使用它做特定于子域的事情,完成后可能会跳转到另一个子域

根据我的经验,在“正常”业务线项目中,您很少会遇到这种情况,但我会这样做:

  • 为通用世界和领域管理创建一个总体的有界上下文。将
    IWorld
    IRealmFactory
    放在那里

  • 为每个游戏系统子域创建单独的有界上下文。它们可以是整个项目,也可以只是名称空间。在这些中编写
    IRealmFactory
    的实现

  • 我认为这是使用
    Container.Resolve(…)
    的少数实例之一。在IoC配置中创建命名注册,并随时解析其中一个,以连接对应于一个游戏系统的对象子图


不要使事情过于复杂。Di容器本身就是一个工厂,通常在应用程序启动时进行配置。我个人在任何项目/组件中都有autofac模块。如果您需要一个真正的工厂,一个基于特定规则创建对象的工厂,它是域的一部分,因为它封装了域规则。对此没有任何行业标准。@JohnathonSullinger“取决于您正在构建的基于文本的游戏类型”=>这是否意味着应用程序的用户是游戏管理员?甚至,他必须为自己的游戏编写模块,从而自己实现
IRealmFactory
。@guillaume31想要构建Mud的人必须是游戏管理员,构建内容。他们可以从一系列不同的设置中进行选择,如D&D构建或Pathfinder构建。我为这些类提供了不同的插件实现,它们通过一个编辑器选择要运行的类。如果他们不喜欢现有的,他们只需要构建一个定制的Irealm。我不想让引擎阻止人们扩展它。这与问题无关,但为什么必须将
IWorld
传递到
IWorld.CreateRealm
?你真的会使用一个世界实例来创建一个属于另一个世界实例的领域吗?不要使事情过于复杂。Di容器本身就是一个工厂,通常在应用程序启动时进行配置。我个人在任何项目/组件中都有autofac模块。如果您需要一个真正的工厂,一个基于特定规则创建对象的工厂,它是域的一部分,因为它封装了域规则。对此没有任何行业标准。@JohnathonSullinger“取决于您正在构建的基于文本的游戏类型”=>这是否意味着应用程序的用户是游戏管理员?甚至,他必须为自己的游戏编写模块,从而自己实现
IRealmFactory
。@guillaume31想要构建Mud的人必须是游戏管理员,构建内容。他们可以从一系列不同的设置中进行选择,如D&D构建或Pathfinder构建。我为这些类提供了不同的插件实现,它们通过一个编辑器选择要运行的类。如果他们不喜欢,他们只需要构建一个定制的Irealm
public interface IWorld : IGameComponent, ICloneableComponent<IWorld>
{
    /// <summary>
    /// Gets how many hours it takes to complete one full day in this world.
    /// </summary>
    int HoursPerDay { get; }

    /// <summary>
    /// Gets or sets the game day to real hour ratio.
    /// </summary>
    double GameDayToRealHourRatio { get; set; }

    /// <summary>
    /// Adds a collection of realms to world, initializing them as they are added.
    /// </summary>
    /// <param name="realms">The realms.</param>
    /// <returns>
    /// Returns an awaitable Task
    /// </returns>
    IRealm[] GetRealmsInWorld();

    /// <summary>
    /// Initializes and then adds the given realm to this world instance.
    /// </summary>
    /// <param name="realm">The realm to add.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task AddRealmToWorld(IRealm realm);

    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner);

    /// <summary>
    /// Adds a collection of realms to world, initializing them as they are added.
    /// </summary>
    /// <param name="realms">The realms.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task AddRealmsToWorld(IEnumerable<IRealm> realms);

    /// <summary>
    /// Removes the given realm from this world instance, deleting the realm in the process.
    /// If it must be reused, you may clone the realm and add the clone to another world.
    /// </summary>
    /// <param name="realm">The realm to remove.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task RemoveRealmFromWorld(IRealm realm);

    /// <summary>
    /// Removes a collection of realms from this world instance.
    /// If any of the realms don't exist in the world, they will be ignored.
    /// The realms will be deleted during the process.
    /// If they must be reused, you may clone the realm and add the clone to another world.
    /// </summary>
    /// <param name="realms">The realms collection.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task RemoveRealmsFromWorld(IEnumerable<IRealm> realms);
}
/// <summary>
/// Provides methods for creating an instance of an IRealm implementation
/// </summary>
public interface IRealmFactory
{
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner);

    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="timeZoneOffset">The time zone offset to apply to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, ITimeOfDay timeZoneOffset);

    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// All of the children zones will be initialized prior to being added to the realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="zones">A collection of zones that will be initialized and added to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, IEnumerable<IZone> zones);

    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// All of the children zones will be initialized prior to being added to the realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="timeZoneOffset">The time zone offset to apply to the realm.</param>
    /// <param name="zones">A collection of zones that will be initialized and added to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, ITimeOfDay timeZoneOffset, IEnumerable<IZone> zones);
}